This script reads in both PBMC and Liver Seurat objects, and generates select figures used in the manuscript.

Prepare objects

Load libraries

library(Seurat)
library(scClustViz)
library(ggplot2)
library(dplyr)
library(rcartocolor)
library(SeuratWrappers)
library(scCustomize)

Read in liver map

sobj <- readRDS("~/Dropbox/Zoe/scf_version/analysis/healthy_sc/seurat_objects/dropletQC_filtered/allIntegrated_cca_kanchor5_noBiopsyHeps_dropletQCFiltered.RDS")
res <- "integrated_snn_res.1.4"
Idents(sobj) <- res
tissue <- "liver"

Read in PBMC map

load("~/Dropbox/Zoe/scf_version/analysis/healthy_sc/seurat_objects/no_dropletQC/integrated_PBMC_cca_kanchor5_scClustViz.RData")
sobj <- scSeurat
res <- "integrated_snn_res.0.6"
Idents(sobj) <- res
tissue <- "PBMC"

Visualization of metadata

UMAP with no cluster numbers

plot <- DimPlot(sobj, label = FALSE) & NoLegend()
plot
pdf(paste("./figures/", tissue, "/", tissue, "_UMAP_clusters_noLabels.pdf", sep = ""))
plot
dev.off()
png 
  2 

UMAP with cluster numbers

plot <- DimPlot(sobj, label = TRUE)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_UMAP_clusters_labels.pdf", sep = ""))
plot
dev.off()
png 
  2 

Map with SCINA-generated cell-type labels

DimPlot(sobj, group.by = "scina_labels_refined", label = TRUE) & NoLegend()

Map with general cell-type labels for paper

plot <- DimPlot(sobj, group.by = "general_cell_labels",
        label = TRUE, repel = TRUE) +
  ggtitle(NULL)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_UMAP_general_cell_labels.pdf", sep = ""),
    height = 8,
    width = 12)
plot
dev.off()
png 
  2 

Map grouping by general cell type labels but with no labels on plot

plot <- DimPlot(sobj, group.by = "general_cell_labels") +
  ggtitle(NULL) &
  NoLegend()
plot
pdf(paste("./figures/", tissue, "/", tissue, "_UMAP_general_cell_labels_noLabels.pdf", 
          sep = ""))
plot
dev.off()
png 
  2 

Map with original identities

plot <- DimPlot(sobj, group.by = "orig.ident",
        cols = carto_pal(length(levels(as.factor(sobj$orig.ident))), "Safe")) +
  ggtitle(NULL)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_UMAP_orig_idents.pdf", 
          sep = ""),
    height = 5, width = 7)
plot
dev.off()
png 
  2 

Barplot with original identities on a cluster-level grouping:

# Meta data to plot:
df <- sobj@meta.data
# Check what column the cluster identities are in
col <- which(colnames(df) == res)
# Order clusters
df[,col] <- factor(Idents(sobj),
                             levels = c(sort(as.numeric(levels(Idents(sobj))))))
# Basic plot of clusters by replicate
ggplot(df, aes(x = get(res), fill = orig.ident)) +
  geom_bar() +
  theme(axis.text = element_text(size = 7))

# Plot as proportion or percentage of cluster
ggplot(df, aes(x = get(res), fill = orig.ident)) +
  geom_bar(position = "fill") +
  theme(axis.text = element_text(size = 7))

Barplot with original identities on a grouped by general cell labels:

df <- sobj@meta.data
plot1 <- ggplot(df, aes(x = general_cell_labels, fill = orig.ident)) +
  geom_bar() +
  scale_fill_carto_d(name = NULL, palette = "Safe") +
  theme_bw() +
  theme(axis.text = element_text(size = 8),
        axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title.x = element_blank()) +
  ylab("Number of cells")
plot1
pdf(paste("./figures/", tissue, "/", tissue, "_barplot_orig_ident_counts.pdf", 
          sep = ""))
plot1
dev.off()
png 
  2 

# Plot as proportion or percentage of cluster
plot2 <- ggplot(df, aes(x = general_cell_labels, fill = orig.ident)) +
  geom_bar(position = "fill") +
  scale_fill_carto_d(name = NULL, palette = "Safe") +
  theme_bw() +
  theme(axis.text = element_text(size = 8),
        axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title.x = element_blank()) +
  ylab("Proportion of cells")
plot2
pdf(paste("./figures/", tissue, "/", tissue, "_barplot_orig_ident_proportions.pdf", 
          sep = ""))
plot2
dev.off()
png 
  2 

Dotplots

Generate dotplot with specific markers

DotPlot(sobj,
        assay = "SCT",
        features = c("PTPRC", "CALCRL", "NKG7", "CD3E", "MARCO", "LYZ-1", "CD19", "MS4A1", "STAB2")
        ) +
  ggtitle("Select features for liver map")

Heatmaps

Calculate markers for general cell labels then reset resolution

Idents(sobj) <- "general_cell_labels"
sobj_markers <- RunPrestoAll(sobj, 
                             only.pos = TRUE, 
                             min.pct = 0.25, 
                             logfc.threshold = 0.25)
Calculating cluster B cells
Calculating cluster CD3+/LEF1+/TCF7+ memory T cells
Calculating cluster CD14-/CD16+ Non-classical monocytes
Calculating cluster Erythrocytes
Calculating cluster CD3+/GATA3+/MAF+ TH2-like T cells 1
Calculating cluster CD14-/CD16- Monocytes
Calculating cluster CD3+/CD8A+/NKG7+ NK-like cells
Calculating cluster CD3+/GATA3+/MAF+ TH2-like T cells 2
Calculating cluster CD14+/CD16+ Monocytes
Calculating cluster Antibody-secreting B cells
Calculating cluster Unknown
Calculating cluster Mast cells
Calculating cluster CD3+/MKI67+/TOP2A+ Proliferating T cells
Calculating cluster Hematopoietic stem cells
Calculating cluster Megakaryocytes
sobj_markers %>%
    group_by(cluster) %>%
    slice_max(n = 2, order_by = avg_log2FC)
Idents(sobj) <- res

Save markers

groups = "general_cell_labels"
write.table(sobj_markers,
            file = paste("./figures/", tissue, "/",
                         tissue, "_markers_", groups, ".tsv", 
                         sep = ""),
            quote = FALSE,
            sep = "\t",
            row.names = FALSE,
            col.names = TRUE)

Generate heatmap with top 5 markers grouping by general cell types

# Remove mikado genes from marker list
sobj_markers <- sobj_markers[grep("mikado", rownames(sobj_markers), invert = TRUE),]
sobj_markers %>%
    group_by(cluster) %>%
    top_n(n = 5, wt = avg_log2FC) -> top
# If liver, select fewer cells
if (tissue == "liver") {
  cells <- sample(colnames(sobj), size = 30000)
} else if (tissue == "PBMC") {
  cells <- colnames(sobj)
}
DoHeatmap(sobj, features = top$gene, group.by = "general_cell_labels", size = 3, 
          angle = 90, cells = cells) +
  NoLegend() +
  theme(text = element_text(size = 7))

Make PDF of heatmap

groups <- "general_cell_labels"
pdf(paste("./figures/", tissue, "/", tissue, "_heatmap_", groups, ".pdf", sep = ""),
    height = 13,
    width = 7)
DoHeatmap(sobj, features = top$gene, group.by = "general_cell_labels", size = 2, 
          angle = 90, cells = cells) +
  NoLegend() +
  theme(text = element_text(size = 7))
dev.off()
null device 
          1 

Feature plots

Make specific plots with specific genes. The genes we are interested in include: PTPRC, CALCRL, NKG7, CD3E, MARCO, LYZ, CD19, MS4A1, STAB2, ALB, CD4, CD8A, CLEC4G, CD5L, C1QB, ACTA2, VWF, IGLL5, CD68. Can also plot in italics.

geneCode <- "sct_LYZ-1" # Woodchuck-specific nomenclature for this genome
gene <- "LYZ"
mapType <- "Liver"
FeaturePlot(sobj, features = geneCode) +
  ggtitle(paste(gene, "-", mapType, "map"))

FeaturePlot(sobj, features = geneCode) +
  ggtitle(bquote(~italic(.(gene))))

Another version of the feature plot that outputs genes in italics

if (tissue == "PBMC") {
 geneCodes <- c("sct_PTPRC","sct_NKG7","sct_CD14",
               "sct_CD3E","sct_MARCO","sct_LYZ-1",
               "sct_CD19","sct_MS4A1","sct_STAB2",
               "sct_CD4","sct_CD8A", "sct_XCL1;XCL2",
               "sct_CD5L","sct_C1QB", "sct_LEF1",
               "sct_ACTA2","sct_VWF","sct_IGLL5-1",
               "sct_CD68","sct_FCGR3A;FCGR3B","sct_TOP2A")
 genes <- c("PTPRC","NKG7","CD14","CD3E","MARCO","LYZ",
           "CD19","MS4A1","STAB2","CD4","CD8A", "XCL1;XCL2",
           "CD5L","C1QB","LEF1","ACTA2","VWF","IGLL5","CD68",
           "FCGR3A;FCGR3B","TOP2A") 
} else if (tissue == "liver") {
  geneCodes <- c("sct_Ptprc","sct_CALCRL","sct_NKG7",
                 "sct_CD3E","sct_MARCO","sct_LYZ-1",
                 "sct_CD19","sct_MS4A1","sct_STAB2",
                 "sct_ALB-1","sct_CD4","sct_CD8A",
                 "sct_CLEC4G","sct_CD5L","sct_C1QB",
                 "sct_ACTA2","sct_VWF","sct_IGLL5-1",
                 "sct_CD68","sct_XCL1;XCL2","sct_LEF1",
                 "sct_RSPO3","sct_MECOM")
  genes <- c("PTPRC","CALCRL","NKG7","CD3E","MARCO","LYZ",
             "CD19","MS4A1","STAB2","ALB","CD4","CD8A",
             "CLEC4G","CD5L","C1QB","ACTA2","VWF","IGLL5","CD68",
             "XCL1;XCL2","LEF1","RSPO3","MECOM") 
}
for(num in 2:length(geneCodes)) {
  plot <- FeaturePlot(sobj,
                      features = geneCodes[num]) +
    ggtitle(bquote(~italic(.(genes[num]))))
  print(plot)
  pdf(paste("./figures/", tissue, "/", tissue, "_", genes[num], "_UMAP.pdf", sep = ""))
  print(plot)
  dev.off()
}

Cell-population-specific markers

Plot marker genes for specific cell populations

Endothelial cells:

geneCodes <- c("STAB2","ITGA1","CD55","LYVE1",
               "CD34","VWF","IFITM3;IFITM2;IFITM1","RSPO3",
               "MECOM","Mecom","CALCRL","LOC114089654",
               "RAMP2","BST2","CLEC4G","CTSV;CTSL",
               "STAB1","PLAC9","PECAM1","WNT2",
               "MYL6","NR2F2")
genes <- c("STAB2","ITGA1","CD55","LYVE1",
           "CD34","VWF","IFITM3","RSPO3",
           "MECOM","Mecom","CALCRL","LOC114089654",
           "RAMP2","BST2","CLEC4G","CTSV;CTSL",
           "STAB1","PLAC9","PECAM1","WNT2",
           "MYL6","NR2F2") 
for(num in 1:length(geneCodes)) {
  plot <- FeaturePlot_scCustom(sobj,
                               features = geneCodes[num],
                               colors_use = viridis_light_high) +
    ggtitle(bquote(~italic(.(genes[num]))))
  print(plot)
  pdf(paste("./figures/", tissue, "/", tissue, "_", genes[num], "_UMAP.pdf", sep = ""))
  print(plot)
  dev.off()
}

Lymphocytes:

Lymphocytes weird genes:

Mesenchyme:

geneCodes <- c("HHIP","COL1A2","COL3A1","IGFBP7",
               "IGFBP3","DCN","COL1A1","SPARC",
               "RBP1", "CALCRL")
genes <- c("HHIP","COL1A2","COL3A1","IGFBP7",
           "IGFBP3","DCN","COL1A1","SPARC",
           "RBP1","CALCRL") 
for(num in 1:length(geneCodes)) {
  plot <- FeaturePlot_scCustom(sobj,
                      features = geneCodes[num],
                      colors_use = viridis_light_high) +
    ggtitle(bquote(~italic(.(genes[num]))))
  print(plot)
  pdf(paste("./figures/", tissue, "/", tissue, "_", genes[num], "_UMAP.pdf", sep = ""))
  print(plot)
  dev.off()
}

Cholangiocytes:

geneCodes <- c("KRT19","CFTR","EPCAM","SLC4A4")
genes <- c("KRT19","CFTR","EPCAM","SLC4A4") 
for(num in 1:length(geneCodes)) {
  plot <- FeaturePlot_scCustom(sobj,
                      features = geneCodes[num],
                      colors_use = viridis_light_high) +
    ggtitle(bquote(~italic(.(genes[num]))))
  print(plot)
  pdf(paste("./figures/", tissue, "/", tissue, "_", genes[num], "_UMAP.pdf", sep = ""))
  print(plot)
  dev.off()
}

Look at zonation gene signatures:

cv_genes <- c("FETUB","HMGCS1","CYP2E1","GLUD1;GLUD2","CYP1A2",
              "RGN","INMT","COMT","FDPS","SPR-1")
cv_genes
 [1] "FETUB"       "HMGCS1"      "CYP2E1"      "GLUD1;GLUD2" "CYP1A2"      "RGN"        
 [7] "INMT"        "COMT"        "FDPS"        "SPR-1"      
pp_genes <- c("Saa2;Saa1-1","HAMP","APOA1","APOC2","CRYL1",
              "AMY1A;AMY1C;AMY1B;AMY2A;AMY2B","MT-ATP6","UROC1",
              "APOA2","MT-CO3")
pp_genes
 [1] "Saa2;Saa1-1"                   "HAMP"                         
 [3] "APOA1"                         "APOC2"                        
 [5] "CRYL1"                         "AMY1A;AMY1C;AMY1B;AMY2A;AMY2B"
 [7] "MT-ATP6"                       "UROC1"                        
 [9] "APOA2"                         "MT-CO3"                       

Cell-type markers all in one plot

Endothelial cells:

# One set of features
geneCodes <- c("STAB2","ITGA1","LYVE1","IFITM3;IFITM2;IFITM1",
               "CALCRL","RAMP2","BST2", "CLEC4G",
               "CTSV;CTSL", "STAB1", "VWF", "CD34",
               "MECOM","PLAC9","RSPO3","WNT2")
# Second set of features
geneCodes <- c("CLEC4G","STAB1","STAB2","LYVE1",
               "CD34","MECOM","VWF","RSPO3",
               "WNT2","ACKR1")
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_endothelialMarkers_UMAP.pdf", sep = ""),
    height = 18, width = 24)
plot
dev.off()
png 
  2 

T lymphocytes

geneCodes <- c("CD3D","CD3E","CD4","CD8A",
               "CTLA4","IL7R-1","LEF1","EOMES",
               "TIGIT","KLRB1","KLRD1","NKG7",
               "XCL1;XCL2","TOX","GZMA","GZMK")
geneCodes <- c("CD3D","CD3E","GIMAP1","GIMAP4",
               "GIMAP6","GIMAP7","CD4","CD28",
               "FOXP1","CTLA4","CD38","XCL1;XCL2",
               "IL2RA","NKG7","CD8A","CCL5",
               "CD69","CD2","GZMK","BRCA2", 
               "TOP2A", "STMN1")
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_lymphocyteMarkers_UMAP.pdf", sep = ""),
    height = ceiling(length(geneCodes)/4)*6, width = 24)
plot
dev.off()
png 
  2 

T lymphocytes for PBMCs

geneCodes <- c("CD3D","CD3E","XCL1;XCL2","NKG7",
               "LEF1","IL7R-1","GATA3","MAF",
               "CCR4","S100A4","CXCR3","IL2RA",
               "CD160","CD247","BRCA2","STMN1")
# CCR7 and TCF7 aren't showing up???
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4,
                     slot = "data")
plot
pdf(paste("./figures/", tissue, "/", tissue, "_lymphocyteMarkers_UMAP.pdf", sep = ""),
    height = ceiling(length(geneCodes)/4)*6, width = 24)
plot
dev.off()
png 
  2 

Mesenchyme:

geneCodes <- c("DCN","COL1A2","COL3A1","HHIP",
               "CALCRL","SPARC","RBP1","COL1A1",
               "IGFBP3", "IGFBP7")
geneCodes <- c("COL1A2", "COL3A1", "IGFBP7", "IGFBP3", 
               "DCN", "CALCRL", "COL1A1", "SPARC", 
               "RBP1", "HHIP","RBP1","LRAT",
               "PDE3B","HGF","CNN2","ACTA2")
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_mesenchymalMarkers_UMAP.pdf", sep = ""),
    height = 24, width = 24)
plot
dev.off()
png 
  2 

Cholangiocytes:

geneCodes <- c("KRT19","SLC4A4","CFTR","EPCAM")
geneCodes <- c("ANXA2", "CST3", "BIRC3", "TESC",
               "KRT19", "SOX9", "EPCAM","SLC4A4",
               "CFTR")
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4)
plot
pdf(paste("./figures/", tissue, "/", tissue, "_cholangiocyteMarkers_UMAP.pdf", sep = ""),
    height = ceiling(length(geneCodes)/4)*6, width = 24)
plot
dev.off()
png 
  2 

Myeloid cells

geneCodes <- c("TYROBP","CD74","CTSS","VSIG4",
               "MARCO", "CD5L","HMOX1","VCAM1",
               "ITGAM","FCGR3A;FCGR3B","Fcgr3;Fcgr2b","CTSA",
               "IL17RA-1","SIRPA;SIRPB1;SIRPG","BTLA", "CADM1",
               "ID2","LY6E","FLT3", "CD14",
               "NOTCH2","LYZ-1","S100A8")
plot <- FeaturePlot_scCustom(sobj,
                     features = geneCodes,
                     colors_use = viridis_light_high,
                     num_columns = 4)
Warning: The following features were omitted as they were not found:
ℹ MARCO, CD5L, HMOX1, VCAM1, CTSA, IL17RA-1, and LYZ-1
plot
pdf(paste("./figures/", tissue, "/", tissue, "_myeloidMarkers_UMAP.pdf", sep = ""),
    height = ceiling(length(geneCodes)/4)*6, width = 24)
plot
dev.off()
png 
  2 

Correlation plots

Generate heatmaps comparing woodchuck clusters with various datasets

Setup for all correlations

First, set up whatever woodchuck dataset I am working with by reading in the ortholog table, choosing whether the orthologs to use are human, mouse, or woodchuck, and calculating the average expression for each cluster. The output of this section is the scaled cluster gene-expression matrix

#groups <- res
groups <- "general_cell_labels"
# Read in ortholog table
geneNameTable <- read.table("~/Dropbox/Zoe/scf_version/make_gtf/orthofinder_sc2/homologene/collectedOrthofinderPairings.tsv",
                            sep = "\t",
                            header = TRUE)
woodchuckClusterAverages <- AverageExpression(sobj,
                                              assays = "SCT",
                                              slot = "scale.data",
                                              group.by = groups)
Warning: `invoke()` is deprecated as of rlang 0.4.0.
# Scale data
woodchuckClusterAverages$SCT <- na.omit(t(scale(t(as.matrix(woodchuckClusterAverages$SCT)))))
# Grab gene names from Seurat object
uniqueHier <- row.names(woodchuckClusterAverages$SCT)
uniqueHier <- as.data.frame(uniqueHier)
# Bind with geneNameTable to get correct order (notice uniqueHier is on left)
newNames <- dplyr::left_join(uniqueHier, geneNameTable, by = "uniqueHier")
# Get orthologs from either mouse or human
species <- "human"
if (species == "human") {
  # If human one-to-one ortho has NA, replace with mikado_final_sc2_stringent_noMito_protein column
  # This is to avoid and potential mistakes in recognizing things it shouldn't be recognizing
  newNames$speciesOneToOne <- ifelse(is.na(newNames$humanOneToOne), newNames$uniqueHier, newNames$humanOneToOne)
} else if (species == "mouse") {
  newNames$speciesOneToOne <- ifelse(is.na(newNames$mouseOneToOne), newNames$uniqueHier, newNames$mouseOneToOne)
} else if (species == "woodchuck") {
  newNames$speciesOneToOne <- newNames$uniqueHier
}
# Grab dataframe
woodchuckClusterAverages <- woodchuckClusterAverages$SCT
# Replace names with one-to-one orthologue of particular species
row.names(woodchuckClusterAverages) <- newNames$speciesOneToOne
# Make sure formatted correctly
woodchuckClusterAverages <- as.data.frame(woodchuckClusterAverages)
# Order by gene name
woodchuckClusterAverages <- woodchuckClusterAverages[order(row.names(woodchuckClusterAverages)),]
# Sanity check
head(woodchuckClusterAverages)

Dataset-specific setup

Correlation of woodchuck PBMCs with human 68k PBMC dataset from 10X Genomics

# Now need to read in 68K PBMC data
humanPBMC <- read.csv("~/Dropbox/Zoe/scf_version/analysis/correlationTests/68K_pbmc_data/68K_enrichedGenes.csv",
                      header = FALSE)
# Get rid of top row
humanPBMC <- humanPBMC[-1,]
# Separate all cell and myloid cell data
allCells <- select(humanPBMC, V1, V2, V3)
myeloid <- select(humanPBMC, V5, V6, V7)
# Rename and get rid of first row
colnames(allCells) <- c("Cluster", "Gene", "Enrichment")
colnames(myeloid) <- c("Cluster", "Gene", "Enrichment")
# Get rid of top row
allCells <- allCells[-1,]
myeloid <- myeloid[-1,]
# I can then filter the rows and bind the data frames back together by gene name
for (j in 1:10) {
  dat <- dplyr::filter(allCells, Cluster == j)
  #dat <- get(paste("allCells", j, sep = ""))
  # Multiply enrichment values by -1 because the signs are backwards???
  dat$Enrichment <- as.numeric(dat$Enrichment) * -1
  dat <- dplyr::select(dat, Gene, Enrichment)
  colnames(dat) <- c("Gene", paste("Enrichment", j, sep = ""))
  if (j == 1) {
    allCellsMatrix <- dat
  }
  else {
    allCellsMatrix <- dplyr::full_join(allCellsMatrix, dat, by = "Gene")
  }
}
# Make row names gene names
rownames(allCellsMatrix) <- allCellsMatrix$Gene
allCellsMatrix <- dplyr::select(allCellsMatrix, -Gene)
# Make column names cell types
colnames(allCellsMatrix) <- c("Activated CD8+", "Naive CD8+", "Memory and Reg T",
                              "Naive CD4+", "NK", "CD8+", "B", "Megakaryocytes",
                              "Monocytes and Dendritic", "B, Dendritic, T")
# Scale across columns
allCellsMatrix <- t(scale(t(allCellsMatrix)))
# Order genes alphabetically by gene name
allCellsMatrix <- allCellsMatrix[order(row.names(allCellsMatrix)),]
# Sanity check
head(allCellsMatrix)
       Activated CD8+ Naive CD8+ Memory and Reg T Naive CD4+          NK
42430      -0.7290166 -1.4467216      -0.19073790 -0.4832807  0.02379348
42431      -0.2300094 -0.7300300      -0.26479348 -0.7995981 -0.18652940
42618      -0.1212209 -0.6309294      -0.09745206 -0.4354971 -0.36419075
A4GALT     -0.4058024 -1.0280327      -0.68648235 -0.4734361 -0.11159565
AATK       -1.0033368 -0.9033733      -0.11847519 -1.0810861 -0.10366579
ABCA1      -0.6939429 -1.0596759      -0.79368826 -0.8411861 -0.88868386
             CD8+          B Megakaryocytes Monocytes and Dendritic
42430  -0.8928406 -0.2258430       1.314882              1.50210970
42431  -0.3474056 -0.6952459       2.578802              0.03087083
42618  -0.8527715 -0.3826776       2.691420             -0.14763062
A4GALT -0.5478332 -0.1352675       2.062829             -0.23671805
AATK   -0.4257702 -0.2369504       1.958543              1.15513309
ABCA1  -0.1144697  0.6312458       1.186970              1.02547753
       B, Dendritic, T
42430        1.1276549
42431        0.6439395
42618        0.3409502
A4GALT       1.5623391
AATK         0.7589817
ABCA1        1.5479533
speciesData <- "68KPBMC"

Correlation of woodchuck liver with human liver dataset from MacParland et al. (2018)

# Find cluster averages of human liver data
load("~/Dropbox/Zoe/scf_version/analysis/correlationTests/HumanLiver.RData")
# Run SCTransform
HumanLiverSeurat <- UpdateSeuratObject(HumanLiverSeurat)
Validating object structure
Updating object slots
Ensuring keys are in the proper structure
Warning: Assay RNA changing from Assay to AssayWarning: DimReduc pca changing from DimReduc to DimReducWarning: DimReduc tsne changing from DimReduc to DimReducEnsuring keys are in the proper structure
Ensuring feature names don't have underscores or pipes
Updating slots in RNA
Updating slots in pca
Updating slots in tsne
Setting tsne DimReduc to global
Validating object structure for Assay ‘RNA’
Validating object structure for DimReduc ‘pca’
Validating object structure for DimReduc ‘tsne’
Object representation is consistent with the most current Seurat version
HumanLiverSeurat <- SCTransform(HumanLiverSeurat)
Running SCTransform on assay: RNA
vst.flavor='v2' set, setting model to use fixed slope and exclude poisson genes.
Calculating cell attributes from input UMI matrix: log_umi
Total Step 1 genes: 17501
Total overdispersed genes: 14764
Excluding 2737 genes from Step 1 because they are not overdispersed.
Variance stabilizing transformation of count matrix of size 18715 by 8444
Model formula is y ~ log_umi
Get Negative Binomial regression parameters per gene
Using 2000 genes, 5000 cells

  |                                                                            
  |                                                                      |   0%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |==================                                                    |  25%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |===================================                                   |  50%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |====================================================                  |  75%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |======================================================================| 100%
Setting estimate of  117 genes to inf as theta_mm/theta_mle < 1e-3
# of step1 poisson genes (variance < mean): 0
# of low mean genes (mean < 0.001): 1363
Total # of Step1 poisson genes (theta=Inf; variance < mean): 136
Total # of poisson genes (theta=Inf; variance < mean): 3896
Calling offset model for all 3896 poisson genes
Found 156 outliers - those will be ignored in fitting/regularization step

Ignoring theta inf genes
Replacing fit params for 3896 poisson genes by theta=Inf
Setting min_variance based on median UMI:  0.04
Second step: Get residuals using fitted parameters for 18715 genes

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |======                                                                |   8%
  |                                                                            
  |=======                                                               |  11%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |===========                                                           |  16%
  |                                                                            
  |=============                                                         |  18%
  |                                                                            
  |===============                                                       |  21%
  |                                                                            
  |=================                                                     |  24%
  |                                                                            
  |==================                                                    |  26%
  |                                                                            
  |====================                                                  |  29%
  |                                                                            
  |======================                                                |  32%
  |                                                                            
  |========================                                              |  34%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |============================                                          |  39%
  |                                                                            
  |=============================                                         |  42%
  |                                                                            
  |===============================                                       |  45%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |=====================================                                 |  53%
  |                                                                            
  |=======================================                               |  55%
  |                                                                            
  |=========================================                             |  58%
  |                                                                            
  |==========================================                            |  61%
  |                                                                            
  |============================================                          |  63%
  |                                                                            
  |==============================================                        |  66%
  |                                                                            
  |================================================                      |  68%
  |                                                                            
  |==================================================                    |  71%
  |                                                                            
  |====================================================                  |  74%
  |                                                                            
  |=====================================================                 |  76%
  |                                                                            
  |=======================================================               |  79%
  |                                                                            
  |=========================================================             |  82%
  |                                                                            
  |===========================================================           |  84%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  89%
  |                                                                            
  |================================================================      |  92%
  |                                                                            
  |==================================================================    |  95%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%
Computing corrected count matrix for 18715 genes

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |======                                                                |   8%
  |                                                                            
  |=======                                                               |  11%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |===========                                                           |  16%
  |                                                                            
  |=============                                                         |  18%
  |                                                                            
  |===============                                                       |  21%
  |                                                                            
  |=================                                                     |  24%
  |                                                                            
  |==================                                                    |  26%
  |                                                                            
  |====================                                                  |  29%
  |                                                                            
  |======================                                                |  32%
  |                                                                            
  |========================                                              |  34%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |============================                                          |  39%
  |                                                                            
  |=============================                                         |  42%
  |                                                                            
  |===============================                                       |  45%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |=====================================                                 |  53%
  |                                                                            
  |=======================================                               |  55%
  |                                                                            
  |=========================================                             |  58%
  |                                                                            
  |==========================================                            |  61%
  |                                                                            
  |============================================                          |  63%
  |                                                                            
  |==============================================                        |  66%
  |                                                                            
  |================================================                      |  68%
  |                                                                            
  |==================================================                    |  71%
  |                                                                            
  |====================================================                  |  74%
  |                                                                            
  |=====================================================                 |  76%
  |                                                                            
  |=======================================================               |  79%
  |                                                                            
  |=========================================================             |  82%
  |                                                                            
  |===========================================================           |  84%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  89%
  |                                                                            
  |================================================================      |  92%
  |                                                                            
  |==================================================================    |  95%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%
Calculating gene attributes
Wall clock passed: Time difference of 1.941124 mins
Determine variable features
Centering data matrix

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |======================================================================| 100%
Place corrected count matrix in counts slot
Set default assay to SCT
humanClusterAverages <- AverageExpression(HumanLiverSeurat,
                                          assays = "SCT",
                                          slot = "scale.data")
# Replace cluster numbers with names
colnames(humanClusterAverages$SCT) <- c("Hep 1", "Alpha-beta T cells", "Hep 2",
                                        "Inflammatory macs", "Hep 3", "Hep 4",
                                        "Plasma cells", "NK-like cells", "Gamma-delta T cells",
                                        "Non-inflammatory macs", "Periportal LSECs", "Central venous LSECs",
                                        "Portal endothelial cells", "Hep 5", "Hep 6",
                                        "Mature B cells", "Cholangiocytes", "Gamma-delta T cells 2",
                                        "Erythroid cells", "Hepatic stellate cells")
# If only looking at specific clusters
#humanClusterAverages$SCT <- humanClusterAverages$SCT[,c("3","1","15","6","14","5")]
# Otherwise go straight to here:
humanClusterAverages$SCT <- na.omit(t(scale(t(as.matrix(humanClusterAverages$SCT)))))
# Grab gene names
humanGenes <- row.names(humanClusterAverages$SCT)
# Now turn into large dataframe
allCellsMatrix <- as.data.frame(humanClusterAverages$SCT)
# Order by row name
allCellsMatrix <- allCellsMatrix[order(row.names(allCellsMatrix)),]
# Sanity check
head(allCellsMatrix)
speciesData <- "macparland"

Correlation of woodchuck liver with human liver dataset from Aizarani et al.

# Read in Aizarani dataset
aizarani <- readRDS("~/Dropbox/Zoe/scf_version/analysis/correlationTests/GSE124395_Normalhumanliverdata.RData")
# Read in clusters and label cells
aizaraniClusters <- read.table("~/Dropbox/Zoe/scf_version/analysis/correlationTests/GSE124395_clusterpartition.txt")
# Only keep cells in the cluster object
aizarani <- aizarani[,intersect(colnames(aizarani),row.names(aizaraniClusters))]
# Create Seurat object
aizarani <- CreateSeuratObject(counts = aizarani)
Counts matrix provided is not sparse. Creating V5 assay in Seurat Object.
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
# Run SCTransform
aizarani <- SCTransform(aizarani)
Running SCTransform on assay: RNA
Running SCTransform on layer: counts
Using block 2 from counts to learn model.
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Getting residuals for block 1(of 3) for counts dataset
Getting residuals for block 2(of 3) for counts dataset
Getting residuals for block 3(of 3) for counts dataset
Centering data matrix

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |======================================================================| 100%
Finished calculating residuals for counts
Set default assay to SCT
# Add cluster IDs
Idents(aizarani) <- aizaraniClusters$sct.cpart
# Get cluster averages
aizaraniAverages <- AverageExpression(aizarani,
                                      assays = "SCT",
                                      slot = "scale.data")
aizaraniAverages$SCT <- na.omit(t(scale(t(as.matrix(aizaraniAverages$SCT)))))
# Grab gene names
aizaraniGenes <- row.names(aizaraniAverages$SCT)
# Now turn into large dataframe
allCellsMatrix <- as.data.frame(aizaraniAverages$SCT)
# Order by column
allCellsMatrix <- allCellsMatrix[,as.character(sort(as.numeric(colnames(allCellsMatrix))))]
# Rename columns to be more meaningful (not totally confident I got all correct)
colnames(allCellsMatrix) <- c('NK, NKT and T cells (1)',
                              'Kupffer cells (2)',
                              'NK, NKT and T cells (3)',
                              'EPCAM+ cells and cholangiocytes (4)',
                              'NK, NKT and T cells (5)',
                              'Kupffer cells (6)',
                              'EPCAM+ cells and cholangiocytes (7)',
                              'B cells (8)',
                              'Liver sinusoidal endothelial cells (9)',
                              'Macrovascular endothelial cells (10)',
                              'Hepatocytes (11)',
                              'NK, NKT and T cells (12)',
                              'Liver sinusoidal endothelial cells (13)',
                              'Hepatocytes (14)',
                              'Other endothelial cells (15)',
                              'Other (16)',
                              'Hepatocytes (17)',
                              'NK, NKT and T cells (18)',
                              'NK, NKT and T cells (19)',
                              'Liver sinusoidal endothelial cells (20)',
                              'Macrovascular endothelial cells (21)',
                              'B cells (22)',
                              'Kupffer cells (23)',
                              'EPCAM+ cells and cholangiocytes (24)',
                              'Kupffer cells (25)',
                              'Other endothelial cells (26)',
                              'Other (27)',
                              'NK, NKT and T cells (28)',
                              'Macrovascular endothelial cells (29)',
                              'Hepatocytes (30)',
                              'Kupffer cells (31)',
                              'Macrovascular endothelial cells (32)',
                              'Stellate cells and myofibroblasts (33)',
                              'B cells (34)',
                              'Other endothelial cells (35)',
                              'Other (36)',
                              'Other (37)',
                              'B cells (38)',
                              'EPCAM+ cells and cholangiocytes (39)')
# Order by row name
allCellsMatrix <- allCellsMatrix[order(row.names(allCellsMatrix)),]
# Sanity check
head(allCellsMatrix)
speciesData <- "aizarani"

Correlation of woodchuck liver with human liver dataset from Andrews et al. (2022)

# Load dataset
humanNuc <- readRDS("~/Dropbox/Zoe/scf_version/analysis/correlationTests/single_nuc_20_human_map.rds")
# Isolate single-nuc only
humanNuc <- UpdateSeuratObject(humanNuc)
Validating object structure
Updating object slots
Ensuring keys are in the proper structure
Warning: Assay RNA changing from Assay to AssayWarning: Graph RNA_nn changing from Graph to GraphWarning: Graph RNA_snn changing from Graph to GraphWarning: DimReduc pca changing from DimReduc to DimReducWarning: DimReduc tsne changing from DimReduc to DimReducWarning: DimReduc umap changing from DimReduc to DimReducWarning: DimReduc harmony changing from DimReduc to DimReducEnsuring keys are in the proper structure
Ensuring feature names don't have underscores or pipes
Updating slots in RNA
Updating slots in RNA_nn
Setting default assay of RNA_nn to RNA
Updating slots in RNA_snn
Setting default assay of RNA_snn to RNA
Updating slots in pca
Updating slots in tsne
Setting tsne DimReduc to global
Updating slots in umap
Setting umap DimReduc to global
Updating slots in harmony
Setting assay used for RunPCA.RNA to RNA
Setting assay used for RunUMAP.RNA.pca to RNA
Setting assay used for Seurat..ProjectDim.RNA.harmony to RNA
Setting assay used for RunUMAP.RNA.harmony to RNA
No assay information could be found for RunTSNE
Warning: Adding a command log without an assay associated with itSetting assay used for FindNeighbors.RNA.harmony to RNA
No assay information could be found for FindClusters
Warning: Adding a command log without an assay associated with itValidating object structure for Assay ‘RNA’
Validating object structure for Graph ‘RNA_nn’
Validating object structure for Graph ‘RNA_snn’
Validating object structure for DimReduc ‘pca’
Validating object structure for DimReduc ‘tsne’
Validating object structure for DimReduc ‘umap’
Validating object structure for DimReduc ‘harmony’
Object representation is consistent with the most current Seurat version
humanNuc <- subset(humanNuc, subset = assay_type == "single_nuc")
# Run SCTransform
humanNuc <- SCTransform(humanNuc)
Running SCTransform on assay: RNA
vst.flavor='v2' set, setting model to use fixed slope and exclude poisson genes.
Calculating cell attributes from input UMI matrix: log_umi
Total Step 1 genes: 10432
Total overdispersed genes: 10429
Excluding 3 genes from Step 1 because they are not overdispersed.
Variance stabilizing transformation of count matrix of size 10432 by 43863
Model formula is y ~ log_umi
Get Negative Binomial regression parameters per gene
Using 2000 genes, 5000 cells

  |                                                                            
  |                                                                      |   0%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |==================                                                    |  25%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |===================================                                   |  50%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |====================================================                  |  75%
Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.Warning: useNames = NA is deprecated. Instead, specify either useNames = TRUE or useNames = TRUE.

  |                                                                            
  |======================================================================| 100%
Setting estimate of  97 genes to inf as theta_mm/theta_mle < 1e-3
# of step1 poisson genes (variance < mean): 0
# of low mean genes (mean < 0.001): 0
Total # of Step1 poisson genes (theta=Inf; variance < mean): 97
Total # of poisson genes (theta=Inf; variance < mean): 3
Calling offset model for all 3 poisson genes
Found 179 outliers - those will be ignored in fitting/regularization step

Ignoring theta inf genes
Replacing fit params for 3 poisson genes by theta=Inf
Setting min_variance based on median UMI:  0.04
Second step: Get residuals using fitted parameters for 10432 genes

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===                                                                   |   5%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |==========                                                            |  14%
  |                                                                            
  |=============                                                         |  19%
  |                                                                            
  |=================                                                     |  24%
  |                                                                            
  |====================                                                  |  29%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |===========================                                           |  38%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |=================================                                     |  48%
  |                                                                            
  |=====================================                                 |  52%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |===========================================                           |  62%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |==================================================                    |  71%
  |                                                                            
  |=====================================================                 |  76%
  |                                                                            
  |=========================================================             |  81%
  |                                                                            
  |============================================================          |  86%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |===================================================================   |  95%
  |                                                                            
  |======================================================================| 100%
Computing corrected count matrix for 10432 genes

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===                                                                   |   5%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |==========                                                            |  14%
  |                                                                            
  |=============                                                         |  19%
  |                                                                            
  |=================                                                     |  24%
  |                                                                            
  |====================                                                  |  29%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |===========================                                           |  38%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |=================================                                     |  48%
  |                                                                            
  |=====================================                                 |  52%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |===========================================                           |  62%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |==================================================                    |  71%
  |                                                                            
  |=====================================================                 |  76%
  |                                                                            
  |=========================================================             |  81%
  |                                                                            
  |============================================================          |  86%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |===================================================================   |  95%
  |                                                                            
  |======================================================================| 100%
Calculating gene attributes
Wall clock passed: Time difference of 1.578703 mins
Determine variable features
Centering data matrix

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |======================================================================| 100%
Place corrected count matrix in counts slot
Set default assay to SCT
# Change idents
Idents(humanNuc) <- humanNuc@meta.data$sub_annotation
# Get cluster averages
humanNucClustAverages <- AverageExpression(humanNuc,
                                           assays = "SCT",
                                           slot = "scale.data")
Warning: `invoke()` is deprecated as of rlang 0.4.0.
humanNucClustAverages$SCT <- na.omit(t(scale(t(as.matrix(humanNucClustAverages$SCT)))))
# Grab gene names
nucGenes <- row.names(humanNucClustAverages$SCT)
# Now turn into large dataframe
allCellsMatrix <- as.data.frame(humanNucClustAverages$SCT)
# Order by row name
allCellsMatrix <- allCellsMatrix[order(row.names(allCellsMatrix)),]
# Sanity check
head(allCellsMatrix)
speciesData <- "andrews"

Correlation of woodchuck liver with woodchuck PBMCs. For this correlation, read in the woodchuck liver dataset at the beginning of this script and then read in the woodchuck PBMCs below

groups <- "general_cell_labels"
# Start with liver and read in woodchuck PBMCs again
load("~/Dropbox/Zoe/scf_version/analysis/healthy_sc/seurat_objects/no_dropletQC/integrated_PBMC_cca_kanchor5_scClustViz.RData")
Idents(scSeurat) <- "integrated_snn_res.0.6"
# Find cluster averages
pbmcClusterAverages <- AverageExpression(scSeurat,
                                         assays = "SCT",
                                         slot = "scale.data",
                                         group.by = groups)
pbmcClusterAverages <- as.data.frame(na.omit(t(scale(t(as.matrix(pbmcClusterAverages$SCT))))))
# Order by row name
allCellsMatrix <- pbmcClusterAverages[order(row.names(pbmcClusterAverages)),]
speciesData <- "PBMC"

Output plots for all correlations

# Now find intersecting genes
matches <- intersect(row.names(allCellsMatrix),
                     row.names(woodchuckClusterAverages))
# Look at how many genes matched
length(matches)
[1] 630
# Make new matrices with only matching gene names
toCor <- allCellsMatrix[matches,]
woodchuckAveragesCor <- woodchuckClusterAverages[matches,]
# Do Pearson
pearVal <- cor(toCor, woodchuckAveragesCor, method = "pearson")
heatmap(pearVal)
        #main = paste("Pearson correlation of", speciesData, "vs", woodchuckData),
        #xlab = woodchuckData,
        #ylab = speciesData)
        #margins = c(6,11))
#Rowv = NA,
#Colv = NA)
pdf(paste("./figures/", tissue, "/", tissue, "_", speciesData, "_PearsonCor.pdf", sep = ""),
    height = 15, width = 13)
heatmap(pearVal, margins = c(13,13))
dev.off()
png 
  2 

# Do Spearman
spearVal <- cor(toCor, woodchuckAveragesCor, method = "spearman")
heatmap(spearVal)
        #main = paste("Spearman correlation of", speciesData, "vs", woodchuckData),
        #xlab = woodchuckData,
        #ylab = speciesData)
        #margins = c(6,11))
#Rowv = NA,
#Colv = NA)
pdf(paste("./figures/", tissue, "/", tissue, "_", speciesData, "_SpearmanCor.pdf", sep = ""),
    height = 15, width = 13)
heatmap(spearVal, margins = c(13,13))
dev.off()
png 
  2 

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBzY3JpcHQgcmVhZHMgaW4gYm90aCBQQk1DIGFuZCBMaXZlciBTZXVyYXQgb2JqZWN0cywgYW5kIGdlbmVyYXRlcyBzZWxlY3QgZmlndXJlcyB1c2VkIGluIHRoZSBtYW51c2NyaXB0LgoKIyMgUHJlcGFyZSBvYmplY3RzCgpMb2FkIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHNjQ2x1c3RWaXopCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShyY2FydG9jb2xvcikKbGlicmFyeShTZXVyYXRXcmFwcGVycykKbGlicmFyeShzY0N1c3RvbWl6ZSkKYGBgCgpSZWFkIGluIGxpdmVyIG1hcAoKYGBge3J9CnNvYmogPC0gcmVhZFJEUygifi9Ecm9wYm94L1pvZS9zY2ZfdmVyc2lvbi9hbmFseXNpcy9oZWFsdGh5X3NjL3NldXJhdF9vYmplY3RzL2Ryb3BsZXRRQ19maWx0ZXJlZC9hbGxJbnRlZ3JhdGVkX2NjYV9rYW5jaG9yNV9ub0Jpb3BzeUhlcHNfZHJvcGxldFFDRmlsdGVyZWQuUkRTIikKcmVzIDwtICJpbnRlZ3JhdGVkX3Nubl9yZXMuMS40IgpJZGVudHMoc29iaikgPC0gcmVzCnRpc3N1ZSA8LSAibGl2ZXIiCmBgYAoKUmVhZCBpbiBQQk1DIG1hcAoKYGBge3J9CmxvYWQoIn4vRHJvcGJveC9ab2Uvc2NmX3ZlcnNpb24vYW5hbHlzaXMvaGVhbHRoeV9zYy9zZXVyYXRfb2JqZWN0cy9ub19kcm9wbGV0UUMvaW50ZWdyYXRlZF9QQk1DX2NjYV9rYW5jaG9yNV9zY0NsdXN0Vml6LlJEYXRhIikKc29iaiA8LSBzY1NldXJhdApyZXMgPC0gImludGVncmF0ZWRfc25uX3Jlcy4wLjYiCklkZW50cyhzb2JqKSA8LSByZXMKdGlzc3VlIDwtICJQQk1DIgpgYGAKCiMjIFZpc3VhbGl6YXRpb24gb2YgbWV0YWRhdGEKClVNQVAgd2l0aCBubyBjbHVzdGVyIG51bWJlcnMKCmBgYHtyfQpwbG90IDwtIERpbVBsb3Qoc29iaiwgbGFiZWwgPSBGQUxTRSkgJiBOb0xlZ2VuZCgpCnBsb3QKcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl9VTUFQX2NsdXN0ZXJzX25vTGFiZWxzLnBkZiIsIHNlcCA9ICIiKSkKcGxvdApkZXYub2ZmKCkKYGBgCgpVTUFQIHdpdGggY2x1c3RlciBudW1iZXJzCgpgYGB7cn0KcGxvdCA8LSBEaW1QbG90KHNvYmosIGxhYmVsID0gVFJVRSkKcGxvdApwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiX1VNQVBfY2x1c3RlcnNfbGFiZWxzLnBkZiIsIHNlcCA9ICIiKSkKcGxvdApkZXYub2ZmKCkKYGBgCgpNYXAgd2l0aCBTQ0lOQS1nZW5lcmF0ZWQgY2VsbC10eXBlIGxhYmVscwoKYGBge3J9CkRpbVBsb3Qoc29iaiwgZ3JvdXAuYnkgPSAic2NpbmFfbGFiZWxzX3JlZmluZWQiLCBsYWJlbCA9IFRSVUUpICYgTm9MZWdlbmQoKQpgYGAKCk1hcCB3aXRoIGdlbmVyYWwgY2VsbC10eXBlIGxhYmVscyBmb3IgcGFwZXIKCmBgYHtyfQpwbG90IDwtIERpbVBsb3Qoc29iaiwgZ3JvdXAuYnkgPSAiZ2VuZXJhbF9jZWxsX2xhYmVscyIsCiAgICAgICAgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUpICsKICBnZ3RpdGxlKE5VTEwpCnBsb3QKcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl9VTUFQX2dlbmVyYWxfY2VsbF9sYWJlbHMucGRmIiwgc2VwID0gIiIpLAogICAgaGVpZ2h0ID0gOCwKICAgIHdpZHRoID0gMTIpCnBsb3QKZGV2Lm9mZigpCmBgYAoKTWFwIGdyb3VwaW5nIGJ5IGdlbmVyYWwgY2VsbCB0eXBlIGxhYmVscyBidXQgd2l0aCBubyBsYWJlbHMgb24gcGxvdAoKYGBge3J9CnBsb3QgPC0gRGltUGxvdChzb2JqLCBncm91cC5ieSA9ICJnZW5lcmFsX2NlbGxfbGFiZWxzIikgKwogIGdndGl0bGUoTlVMTCkgJgogIE5vTGVnZW5kKCkKcGxvdApwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiX1VNQVBfZ2VuZXJhbF9jZWxsX2xhYmVsc19ub0xhYmVscy5wZGYiLCAKICAgICAgICAgIHNlcCA9ICIiKSkKcGxvdApkZXYub2ZmKCkKYGBgCgpNYXAgd2l0aCBvcmlnaW5hbCBpZGVudGl0aWVzCgpgYGB7cn0KcGxvdCA8LSBEaW1QbG90KHNvYmosIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLAogICAgICAgIGNvbHMgPSBjYXJ0b19wYWwobGVuZ3RoKGxldmVscyhhcy5mYWN0b3Ioc29iaiRvcmlnLmlkZW50KSkpLCAiU2FmZSIpKSArCiAgZ2d0aXRsZShOVUxMKQpwbG90CnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfVU1BUF9vcmlnX2lkZW50cy5wZGYiLCAKICAgICAgICAgIHNlcCA9ICIiKSwKICAgIGhlaWdodCA9IDUsIHdpZHRoID0gNykKcGxvdApkZXYub2ZmKCkKYGBgCgpCYXJwbG90IHdpdGggb3JpZ2luYWwgaWRlbnRpdGllcyBvbiBhIGNsdXN0ZXItbGV2ZWwgZ3JvdXBpbmc6CgpgYGB7cn0KIyBNZXRhIGRhdGEgdG8gcGxvdDoKZGYgPC0gc29iakBtZXRhLmRhdGEKIyBDaGVjayB3aGF0IGNvbHVtbiB0aGUgY2x1c3RlciBpZGVudGl0aWVzIGFyZSBpbgpjb2wgPC0gd2hpY2goY29sbmFtZXMoZGYpID09IHJlcykKIyBPcmRlciBjbHVzdGVycwpkZlssY29sXSA8LSBmYWN0b3IoSWRlbnRzKHNvYmopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoc29ydChhcy5udW1lcmljKGxldmVscyhJZGVudHMoc29iaikpKSkpKQojIEJhc2ljIHBsb3Qgb2YgY2x1c3RlcnMgYnkgcmVwbGljYXRlCmdncGxvdChkZiwgYWVzKHggPSBnZXQocmVzKSwgZmlsbCA9IG9yaWcuaWRlbnQpKSArCiAgZ2VvbV9iYXIoKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSkKIyBQbG90IGFzIHByb3BvcnRpb24gb3IgcGVyY2VudGFnZSBvZiBjbHVzdGVyCmdncGxvdChkZiwgYWVzKHggPSBnZXQocmVzKSwgZmlsbCA9IG9yaWcuaWRlbnQpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKQpgYGAKCkJhcnBsb3Qgd2l0aCBvcmlnaW5hbCBpZGVudGl0aWVzIG9uIGEgZ3JvdXBlZCBieSBnZW5lcmFsIGNlbGwgbGFiZWxzOgoKYGBge3J9CmRmIDwtIHNvYmpAbWV0YS5kYXRhCnBsb3QxIDwtIGdncGxvdChkZiwgYWVzKHggPSBnZW5lcmFsX2NlbGxfbGFiZWxzLCBmaWxsID0gb3JpZy5pZGVudCkpICsKICBnZW9tX2JhcigpICsKICBzY2FsZV9maWxsX2NhcnRvX2QobmFtZSA9IE5VTEwsIHBhbGV0dGUgPSAiU2FmZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICB5bGFiKCJOdW1iZXIgb2YgY2VsbHMiKQpwbG90MQpwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiX2JhcnBsb3Rfb3JpZ19pZGVudF9jb3VudHMucGRmIiwgCiAgICAgICAgICBzZXAgPSAiIikpCnBsb3QxCmRldi5vZmYoKQojIFBsb3QgYXMgcHJvcG9ydGlvbiBvciBwZXJjZW50YWdlIG9mIGNsdXN0ZXIKcGxvdDIgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGdlbmVyYWxfY2VsbF9sYWJlbHMsIGZpbGwgPSBvcmlnLmlkZW50KSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArCiAgc2NhbGVfZmlsbF9jYXJ0b19kKG5hbWUgPSBOVUxMLCBwYWxldHRlID0gIlNhZmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBjZWxscyIpCnBsb3QyCnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfYmFycGxvdF9vcmlnX2lkZW50X3Byb3BvcnRpb25zLnBkZiIsIAogICAgICAgICAgc2VwID0gIiIpKQpwbG90MgpkZXYub2ZmKCkKYGBgCgojIyBEb3RwbG90cwoKR2VuZXJhdGUgZG90cGxvdCB3aXRoIHNwZWNpZmljIG1hcmtlcnMKCmBgYHtyfQpEb3RQbG90KHNvYmosCiAgICAgICAgYXNzYXkgPSAiU0NUIiwKICAgICAgICBmZWF0dXJlcyA9IGMoIlBUUFJDIiwgIkNBTENSTCIsICJOS0c3IiwgIkNEM0UiLCAiTUFSQ08iLCAiTFlaLTEiLCAiQ0QxOSIsICJNUzRBMSIsICJTVEFCMiIpCiAgICAgICAgKSArCiAgZ2d0aXRsZSgiU2VsZWN0IGZlYXR1cmVzIGZvciBsaXZlciBtYXAiKQpgYGAKCiMjIEhlYXRtYXBzCgpDYWxjdWxhdGUgbWFya2VycyBmb3IgZ2VuZXJhbCBjZWxsIGxhYmVscyB0aGVuIHJlc2V0IHJlc29sdXRpb24KCmBgYHtyfQpJZGVudHMoc29iaikgPC0gImdlbmVyYWxfY2VsbF9sYWJlbHMiCnNvYmpfbWFya2VycyA8LSBSdW5QcmVzdG9BbGwoc29iaiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25seS5wb3MgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4ucGN0ID0gMC4yNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZmMudGhyZXNob2xkID0gMC4yNSkKc29ial9tYXJrZXJzICU+JQogICAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lCiAgICBzbGljZV9tYXgobiA9IDIsIG9yZGVyX2J5ID0gYXZnX2xvZzJGQykKSWRlbnRzKHNvYmopIDwtIHJlcwpgYGAKClNhdmUgbWFya2VycwoKYGBge3J9Cmdyb3VwcyA9ICJnZW5lcmFsX2NlbGxfbGFiZWxzIgp3cml0ZS50YWJsZShzb2JqX21hcmtlcnMsCiAgICAgICAgICAgIGZpbGUgPSBwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLAogICAgICAgICAgICAgICAgICAgICAgICAgdGlzc3VlLCAiX21hcmtlcnNfIiwgZ3JvdXBzLCAiLnRzdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpLAogICAgICAgICAgICBxdW90ZSA9IEZBTFNFLAogICAgICAgICAgICBzZXAgPSAiXHQiLAogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSkKYGBgCgpHZW5lcmF0ZSBoZWF0bWFwIHdpdGggdG9wIDUgbWFya2VycyBncm91cGluZyBieSBnZW5lcmFsIGNlbGwgdHlwZXMKCmBgYHtyfQojIFJlbW92ZSBtaWthZG8gZ2VuZXMgZnJvbSBtYXJrZXIgbGlzdApzb2JqX21hcmtlcnMgPC0gc29ial9tYXJrZXJzW2dyZXAoIm1pa2FkbyIsIHJvd25hbWVzKHNvYmpfbWFya2VycyksIGludmVydCA9IFRSVUUpLF0Kc29ial9tYXJrZXJzICU+JQogICAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lCiAgICB0b3BfbihuID0gNSwgd3QgPSBhdmdfbG9nMkZDKSAtPiB0b3AKIyBJZiBsaXZlciwgc2VsZWN0IGZld2VyIGNlbGxzCmlmICh0aXNzdWUgPT0gImxpdmVyIikgewogIGNlbGxzIDwtIHNhbXBsZShjb2xuYW1lcyhzb2JqKSwgc2l6ZSA9IDMwMDAwKQp9IGVsc2UgaWYgKHRpc3N1ZSA9PSAiUEJNQyIpIHsKICBjZWxscyA8LSBjb2xuYW1lcyhzb2JqKQp9CkRvSGVhdG1hcChzb2JqLCBmZWF0dXJlcyA9IHRvcCRnZW5lLCBncm91cC5ieSA9ICJnZW5lcmFsX2NlbGxfbGFiZWxzIiwgc2l6ZSA9IDMsIAogICAgICAgICAgYW5nbGUgPSA5MCwgY2VsbHMgPSBjZWxscykgKwogIE5vTGVnZW5kKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKQpgYGAKCk1ha2UgUERGIG9mIGhlYXRtYXAKCmBgYHtyfQpncm91cHMgPC0gImdlbmVyYWxfY2VsbF9sYWJlbHMiCnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfaGVhdG1hcF8iLCBncm91cHMsICIucGRmIiwgc2VwID0gIiIpLAogICAgaGVpZ2h0ID0gMTMsCiAgICB3aWR0aCA9IDcpCkRvSGVhdG1hcChzb2JqLCBmZWF0dXJlcyA9IHRvcCRnZW5lLCBncm91cC5ieSA9ICJnZW5lcmFsX2NlbGxfbGFiZWxzIiwgc2l6ZSA9IDIsIAogICAgICAgICAgYW5nbGUgPSA5MCwgY2VsbHMgPSBjZWxscykgKwogIE5vTGVnZW5kKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKQpkZXYub2ZmKCkKYGBgCgoKIyMgRmVhdHVyZSBwbG90cwoKTWFrZSBzcGVjaWZpYyBwbG90cyB3aXRoIHNwZWNpZmljIGdlbmVzLiBUaGUgZ2VuZXMgd2UgYXJlIGludGVyZXN0ZWQgaW4gaW5jbHVkZTogKlBUUFJDLCBDQUxDUkwsIE5LRzcsIENEM0UsIE1BUkNPLCBMWVosIENEMTksIE1TNEExLCBTVEFCMiwgQUxCLCBDRDQsIENEOEEsIENMRUM0RywgQ0Q1TCwgQzFRQiwgQUNUQTIsIFZXRiwgSUdMTDUsIENENjgqLiBDYW4gYWxzbyBwbG90IGluIGl0YWxpY3MuCgpgYGB7cn0KZ2VuZUNvZGUgPC0gInNjdF9MWVotMSIgIyBXb29kY2h1Y2stc3BlY2lmaWMgbm9tZW5jbGF0dXJlIGZvciB0aGlzIGdlbm9tZQpnZW5lIDwtICJMWVoiCm1hcFR5cGUgPC0gIkxpdmVyIgpGZWF0dXJlUGxvdChzb2JqLCBmZWF0dXJlcyA9IGdlbmVDb2RlKSArCiAgZ2d0aXRsZShwYXN0ZShnZW5lLCAiLSIsIG1hcFR5cGUsICJtYXAiKSkKRmVhdHVyZVBsb3Qoc29iaiwgZmVhdHVyZXMgPSBnZW5lQ29kZSkgKwogIGdndGl0bGUoYnF1b3RlKH5pdGFsaWMoLihnZW5lKSkpKQpgYGAKCkFub3RoZXIgdmVyc2lvbiBvZiB0aGUgZmVhdHVyZSBwbG90IHRoYXQgb3V0cHV0cyBnZW5lcyBpbiBpdGFsaWNzCgpgYGB7cn0KaWYgKHRpc3N1ZSA9PSAiUEJNQyIpIHsKIGdlbmVDb2RlcyA8LSBjKCJzY3RfUFRQUkMiLCJzY3RfTktHNyIsInNjdF9DRDE0IiwKICAgICAgICAgICAgICAgInNjdF9DRDNFIiwic2N0X01BUkNPIiwic2N0X0xZWi0xIiwKICAgICAgICAgICAgICAgInNjdF9DRDE5Iiwic2N0X01TNEExIiwic2N0X1NUQUIyIiwKICAgICAgICAgICAgICAgInNjdF9DRDQiLCJzY3RfQ0Q4QSIsICJzY3RfWENMMTtYQ0wyIiwKICAgICAgICAgICAgICAgInNjdF9DRDVMIiwic2N0X0MxUUIiLCAic2N0X0xFRjEiLAogICAgICAgICAgICAgICAic2N0X0FDVEEyIiwic2N0X1ZXRiIsInNjdF9JR0xMNS0xIiwKICAgICAgICAgICAgICAgInNjdF9DRDY4Iiwic2N0X0ZDR1IzQTtGQ0dSM0IiLCJzY3RfVE9QMkEiKQogZ2VuZXMgPC0gYygiUFRQUkMiLCJOS0c3IiwiQ0QxNCIsIkNEM0UiLCJNQVJDTyIsIkxZWiIsCiAgICAgICAgICAgIkNEMTkiLCJNUzRBMSIsIlNUQUIyIiwiQ0Q0IiwiQ0Q4QSIsICJYQ0wxO1hDTDIiLAogICAgICAgICAgICJDRDVMIiwiQzFRQiIsIkxFRjEiLCJBQ1RBMiIsIlZXRiIsIklHTEw1IiwiQ0Q2OCIsCiAgICAgICAgICAgIkZDR1IzQTtGQ0dSM0IiLCJUT1AyQSIpIAp9IGVsc2UgaWYgKHRpc3N1ZSA9PSAibGl2ZXIiKSB7CiAgZ2VuZUNvZGVzIDwtIGMoInNjdF9QdHByYyIsInNjdF9DQUxDUkwiLCJzY3RfTktHNyIsCiAgICAgICAgICAgICAgICAgInNjdF9DRDNFIiwic2N0X01BUkNPIiwic2N0X0xZWi0xIiwKICAgICAgICAgICAgICAgICAic2N0X0NEMTkiLCJzY3RfTVM0QTEiLCJzY3RfU1RBQjIiLAogICAgICAgICAgICAgICAgICJzY3RfQUxCLTEiLCJzY3RfQ0Q0Iiwic2N0X0NEOEEiLAogICAgICAgICAgICAgICAgICJzY3RfQ0xFQzRHIiwic2N0X0NENUwiLCJzY3RfQzFRQiIsCiAgICAgICAgICAgICAgICAgInNjdF9BQ1RBMiIsInNjdF9WV0YiLCJzY3RfSUdMTDUtMSIsCiAgICAgICAgICAgICAgICAgInNjdF9DRDY4Iiwic2N0X1hDTDE7WENMMiIsInNjdF9MRUYxIiwKICAgICAgICAgICAgICAgICAic2N0X1JTUE8zIiwic2N0X01FQ09NIikKICBnZW5lcyA8LSBjKCJQVFBSQyIsIkNBTENSTCIsIk5LRzciLCJDRDNFIiwiTUFSQ08iLCJMWVoiLAogICAgICAgICAgICAgIkNEMTkiLCJNUzRBMSIsIlNUQUIyIiwiQUxCIiwiQ0Q0IiwiQ0Q4QSIsCiAgICAgICAgICAgICAiQ0xFQzRHIiwiQ0Q1TCIsIkMxUUIiLCJBQ1RBMiIsIlZXRiIsIklHTEw1IiwiQ0Q2OCIsCiAgICAgICAgICAgICAiWENMMTtYQ0wyIiwiTEVGMSIsIlJTUE8zIiwiTUVDT00iKSAKfQpmb3IobnVtIGluIDI6bGVuZ3RoKGdlbmVDb2RlcykpIHsKICBwbG90IDwtIEZlYXR1cmVQbG90KHNvYmosCiAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmVDb2Rlc1tudW1dKSArCiAgICBnZ3RpdGxlKGJxdW90ZSh+aXRhbGljKC4oZ2VuZXNbbnVtXSkpKSkKICBwcmludChwbG90KQogIHBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfIiwgZ2VuZXNbbnVtXSwgIl9VTUFQLnBkZiIsIHNlcCA9ICIiKSkKICBwcmludChwbG90KQogIGRldi5vZmYoKQp9CmBgYAoKIyMjIENlbGwtcG9wdWxhdGlvbi1zcGVjaWZpYyBtYXJrZXJzCgpQbG90IG1hcmtlciBnZW5lcyBmb3Igc3BlY2lmaWMgY2VsbCBwb3B1bGF0aW9ucwoKRW5kb3RoZWxpYWwgY2VsbHM6CgpgYGB7cn0KZ2VuZUNvZGVzIDwtIGMoIlNUQUIyIiwiSVRHQTEiLCJDRDU1IiwiTFlWRTEiLAogICAgICAgICAgICAgICAiQ0QzNCIsIlZXRiIsIklGSVRNMztJRklUTTI7SUZJVE0xIiwiUlNQTzMiLAogICAgICAgICAgICAgICAiTUVDT00iLCJNZWNvbSIsIkNBTENSTCIsIkxPQzExNDA4OTY1NCIsCiAgICAgICAgICAgICAgICJSQU1QMiIsIkJTVDIiLCJDTEVDNEciLCJDVFNWO0NUU0wiLAogICAgICAgICAgICAgICAiU1RBQjEiLCJQTEFDOSIsIlBFQ0FNMSIsIldOVDIiLAogICAgICAgICAgICAgICAiTVlMNiIsIk5SMkYyIikKZ2VuZXMgPC0gYygiU1RBQjIiLCJJVEdBMSIsIkNENTUiLCJMWVZFMSIsCiAgICAgICAgICAgIkNEMzQiLCJWV0YiLCJJRklUTTMiLCJSU1BPMyIsCiAgICAgICAgICAgIk1FQ09NIiwiTWVjb20iLCJDQUxDUkwiLCJMT0MxMTQwODk2NTQiLAogICAgICAgICAgICJSQU1QMiIsIkJTVDIiLCJDTEVDNEciLCJDVFNWO0NUU0wiLAogICAgICAgICAgICJTVEFCMSIsIlBMQUM5IiwiUEVDQU0xIiwiV05UMiIsCiAgICAgICAgICAgIk1ZTDYiLCJOUjJGMiIpIApmb3IobnVtIGluIDE6bGVuZ3RoKGdlbmVDb2RlcykpIHsKICBwbG90IDwtIEZlYXR1cmVQbG90X3NjQ3VzdG9tKHNvYmosCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmVDb2Rlc1tudW1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzX3VzZSA9IHZpcmlkaXNfbGlnaHRfaGlnaCkgKwogICAgZ2d0aXRsZShicXVvdGUofml0YWxpYyguKGdlbmVzW251bV0pKSkpCiAgcHJpbnQocGxvdCkKICBwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiXyIsIGdlbmVzW251bV0sICJfVU1BUC5wZGYiLCBzZXAgPSAiIikpCiAgcHJpbnQocGxvdCkKICBkZXYub2ZmKCkKfQpgYGAKCkx5bXBob2N5dGVzOgoKYGBge3J9CmdlbmVDb2RlcyA8LSBjKCJDWENSMyIsIklMN1ItMSIsCiAgICAgICAgICAgICAgICJTMTAwQTQiLCJHQVRBMyIsIkNEMjQ3IiwiTUFGIiwKICAgICAgICAgICAgICAgIkNDUjQiKQpnZW5lcyA8LSBnZW5lQ29kZXMKZ2VuZUNvZGVzIDwtIGMoIkNEM0QiLCJDRDNFIiwiQ0Q4QSIsIk5LRzciLAogICAgICAgICAgICAgICAiS0xSRDEiLCJLTFJCMSIsIkdaTUEiLCJMRUYxIiwKICAgICAgICAgICAgICAgIklMN1ItMSIsIkVPTUVTIiwiVElHSVQiLCJYQ0wxO1hDTDIiLAogICAgICAgICAgICAgICAiVE9YIiwiQ1RMQTQiLCJDRDQiLCJHWk1LIikKZ2VuZXMgPC0gYygiQ0QzRCIsIkNEM0UiLCJDRDhBIiwiTktHNyIsCiAgICAgICAgICAgIktMUkQxIiwiS0xSQjEiLCJHWk1BIiwiTEVGMSIsCiAgICAgICAgICAgIklMN1IiLCJFT01FUyIsIlRJR0lUIiwiWENMMTtYQ0wyIiwKICAgICAgICAgICAiVE9YIiwiQ1RMQTQiLCJDRDQiLCJHWk1LIikgCmZvcihudW0gaW4gMTpsZW5ndGgoZ2VuZUNvZGVzKSkgewogIHBsb3QgPC0gRmVhdHVyZVBsb3Rfc2NDdXN0b20oc29iaiwKICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gZ2VuZUNvZGVzW251bV0sCiAgICAgICAgICAgICAgICAgICAgICBjb2xvcnNfdXNlID0gdmlyaWRpc19saWdodF9oaWdoKSArCiAgICBnZ3RpdGxlKGJxdW90ZSh+aXRhbGljKC4oZ2VuZXNbbnVtXSkpKSkKICBwcmludChwbG90KQogIHBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfIiwgZ2VuZXNbbnVtXSwgIl9VTUFQLnBkZiIsIHNlcCA9ICIiKSkKICBwcmludChwbG90KQogIGRldi5vZmYoKQp9CmBgYAoKTHltcGhvY3l0ZXMgd2VpcmQgZ2VuZXM6CgpgYGB7cn0KZ2VuZUNvZGVzIDwtIGMoInNjdF9DQ1I3IikKZ2VuZXMgPC0gZ2VuZUNvZGVzCiNwbG90IDwtIEZlYXR1cmVQbG90X3NjQ3VzdG9tKHNvYmosCiMgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBnZW5lQ29kZXMsCiMgICAgICAgICAgICAgICAgICAgICAgY29sb3JzX3VzZSA9IHZpcmlkaXNfbGlnaHRfaGlnaCkgKwojICAgIGdndGl0bGUoYnF1b3RlKH5pdGFsaWMoLihnZW5lcykpKSkKcGxvdCA8LSBGZWF0dXJlUGxvdChzb2JqLCBmZWF0dXJlcyA9ICJzY3RfQ0NSNyIpCnByaW50KHBsb3QpCmBgYAoKCk1lc2VuY2h5bWU6CgpgYGB7cn0KZ2VuZUNvZGVzIDwtIGMoIkhISVAiLCJDT0wxQTIiLCJDT0wzQTEiLCJJR0ZCUDciLAogICAgICAgICAgICAgICAiSUdGQlAzIiwiRENOIiwiQ09MMUExIiwiU1BBUkMiLAogICAgICAgICAgICAgICAiUkJQMSIsICJDQUxDUkwiKQpnZW5lcyA8LSBjKCJISElQIiwiQ09MMUEyIiwiQ09MM0ExIiwiSUdGQlA3IiwKICAgICAgICAgICAiSUdGQlAzIiwiRENOIiwiQ09MMUExIiwiU1BBUkMiLAogICAgICAgICAgICJSQlAxIiwiQ0FMQ1JMIikgCmZvcihudW0gaW4gMTpsZW5ndGgoZ2VuZUNvZGVzKSkgewogIHBsb3QgPC0gRmVhdHVyZVBsb3Rfc2NDdXN0b20oc29iaiwKICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gZ2VuZUNvZGVzW251bV0sCiAgICAgICAgICAgICAgICAgICAgICBjb2xvcnNfdXNlID0gdmlyaWRpc19saWdodF9oaWdoKSArCiAgICBnZ3RpdGxlKGJxdW90ZSh+aXRhbGljKC4oZ2VuZXNbbnVtXSkpKSkKICBwcmludChwbG90KQogIHBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfIiwgZ2VuZXNbbnVtXSwgIl9VTUFQLnBkZiIsIHNlcCA9ICIiKSkKICBwcmludChwbG90KQogIGRldi5vZmYoKQp9CmBgYAoKQ2hvbGFuZ2lvY3l0ZXM6CgpgYGB7cn0KZ2VuZUNvZGVzIDwtIGMoIktSVDE5IiwiQ0ZUUiIsIkVQQ0FNIiwiU0xDNEE0IikKZ2VuZXMgPC0gYygiS1JUMTkiLCJDRlRSIiwiRVBDQU0iLCJTTEM0QTQiKSAKZm9yKG51bSBpbiAxOmxlbmd0aChnZW5lQ29kZXMpKSB7CiAgcGxvdCA8LSBGZWF0dXJlUGxvdF9zY0N1c3RvbShzb2JqLAogICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBnZW5lQ29kZXNbbnVtXSwKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yc191c2UgPSB2aXJpZGlzX2xpZ2h0X2hpZ2gpICsKICAgIGdndGl0bGUoYnF1b3RlKH5pdGFsaWMoLihnZW5lc1tudW1dKSkpKQogIHByaW50KHBsb3QpCiAgcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl8iLCBnZW5lc1tudW1dLCAiX1VNQVAucGRmIiwgc2VwID0gIiIpKQogIHByaW50KHBsb3QpCiAgZGV2Lm9mZigpCn0KYGBgCgpMb29rIGF0IHpvbmF0aW9uIGdlbmUgc2lnbmF0dXJlczoKCmBgYHtyfQpjdl9nZW5lcyA8LSBjKCJGRVRVQiIsIkhNR0NTMSIsIkNZUDJFMSIsIkdMVUQxO0dMVUQyIiwiQ1lQMUEyIiwKICAgICAgICAgICAgICAiUkdOIiwiSU5NVCIsIkNPTVQiLCJGRFBTIiwiU1BSLTEiKQpjdl9nZW5lcwpwcF9nZW5lcyA8LSBjKCJTYWEyO1NhYTEtMSIsIkhBTVAiLCJBUE9BMSIsIkFQT0MyIiwiQ1JZTDEiLAogICAgICAgICAgICAgICJBTVkxQTtBTVkxQztBTVkxQjtBTVkyQTtBTVkyQiIsIk1ULUFUUDYiLCJVUk9DMSIsCiAgICAgICAgICAgICAgIkFQT0EyIiwiTVQtQ08zIikKcHBfZ2VuZXMKYGBgCgojIyMgQ2VsbC10eXBlIG1hcmtlcnMgYWxsIGluIG9uZSBwbG90CgpFbmRvdGhlbGlhbCBjZWxsczoKCmBgYHtyfQojIE9uZSBzZXQgb2YgZmVhdHVyZXMKZ2VuZUNvZGVzIDwtIGMoIlNUQUIyIiwiSVRHQTEiLCJMWVZFMSIsIklGSVRNMztJRklUTTI7SUZJVE0xIiwKICAgICAgICAgICAgICAgIkNBTENSTCIsIlJBTVAyIiwiQlNUMiIsICJDTEVDNEciLAogICAgICAgICAgICAgICAiQ1RTVjtDVFNMIiwgIlNUQUIxIiwgIlZXRiIsICJDRDM0IiwKICAgICAgICAgICAgICAgIk1FQ09NIiwiUExBQzkiLCJSU1BPMyIsIldOVDIiKQojIFNlY29uZCBzZXQgb2YgZmVhdHVyZXMKZ2VuZUNvZGVzIDwtIGMoIkNMRUM0RyIsIlNUQUIxIiwiU1RBQjIiLCJMWVZFMSIsCiAgICAgICAgICAgICAgICJDRDM0IiwiTUVDT00iLCJWV0YiLCJSU1BPMyIsCiAgICAgICAgICAgICAgICJXTlQyIiwiQUNLUjEiKQpwbG90IDwtIEZlYXR1cmVQbG90X3NjQ3VzdG9tKHNvYmosCiAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gZ2VuZUNvZGVzLAogICAgICAgICAgICAgICAgICAgICBjb2xvcnNfdXNlID0gdmlyaWRpc19saWdodF9oaWdoLAogICAgICAgICAgICAgICAgICAgICBudW1fY29sdW1ucyA9IDQpCnBsb3QKcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl9lbmRvdGhlbGlhbE1hcmtlcnNfVU1BUC5wZGYiLCBzZXAgPSAiIiksCiAgICBoZWlnaHQgPSAxOCwgd2lkdGggPSAyNCkKcGxvdApkZXYub2ZmKCkKYGBgCgpUIGx5bXBob2N5dGVzCgpgYGB7cn0KZ2VuZUNvZGVzIDwtIGMoIkNEM0QiLCJDRDNFIiwiQ0Q0IiwiQ0Q4QSIsCiAgICAgICAgICAgICAgICJDVExBNCIsIklMN1ItMSIsIkxFRjEiLCJFT01FUyIsCiAgICAgICAgICAgICAgICJUSUdJVCIsIktMUkIxIiwiS0xSRDEiLCJOS0c3IiwKICAgICAgICAgICAgICAgIlhDTDE7WENMMiIsIlRPWCIsIkdaTUEiLCJHWk1LIikKZ2VuZUNvZGVzIDwtIGMoIkNEM0QiLCJDRDNFIiwiR0lNQVAxIiwiR0lNQVA0IiwKICAgICAgICAgICAgICAgIkdJTUFQNiIsIkdJTUFQNyIsIkNENCIsIkNEMjgiLAogICAgICAgICAgICAgICAiRk9YUDEiLCJDVExBNCIsIkNEMzgiLCJYQ0wxO1hDTDIiLAogICAgICAgICAgICAgICAiSUwyUkEiLCJOS0c3IiwiQ0Q4QSIsIkNDTDUiLAogICAgICAgICAgICAgICAiQ0Q2OSIsIkNEMiIsIkdaTUsiLCJCUkNBMiIsIAogICAgICAgICAgICAgICAiVE9QMkEiLCAiU1RNTjEiKQpwbG90IDwtIEZlYXR1cmVQbG90X3NjQ3VzdG9tKHNvYmosCiAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gZ2VuZUNvZGVzLAogICAgICAgICAgICAgICAgICAgICBjb2xvcnNfdXNlID0gdmlyaWRpc19saWdodF9oaWdoLAogICAgICAgICAgICAgICAgICAgICBudW1fY29sdW1ucyA9IDQpCnBsb3QKcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl9seW1waG9jeXRlTWFya2Vyc19VTUFQLnBkZiIsIHNlcCA9ICIiKSwKICAgIGhlaWdodCA9IGNlaWxpbmcobGVuZ3RoKGdlbmVDb2RlcykvNCkqNiwgd2lkdGggPSAyNCkKcGxvdApkZXYub2ZmKCkKYGBgCgpUIGx5bXBob2N5dGVzIGZvciBQQk1DcwoKYGBge3J9CmdlbmVDb2RlcyA8LSBjKCJDRDNEIiwiQ0QzRSIsIlhDTDE7WENMMiIsIk5LRzciLAogICAgICAgICAgICAgICAiTEVGMSIsIklMN1ItMSIsIkdBVEEzIiwiTUFGIiwKICAgICAgICAgICAgICAgIkNDUjQiLCJTMTAwQTQiLCJDWENSMyIsIklMMlJBIiwKICAgICAgICAgICAgICAgIkNEMTYwIiwiQ0QyNDciLCJCUkNBMiIsIlNUTU4xIikKIyBDQ1I3IGFuZCBUQ0Y3IGFyZW4ndCBzaG93aW5nIHVwPz8/CnBsb3QgPC0gRmVhdHVyZVBsb3Rfc2NDdXN0b20oc29iaiwKICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBnZW5lQ29kZXMsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yc191c2UgPSB2aXJpZGlzX2xpZ2h0X2hpZ2gsCiAgICAgICAgICAgICAgICAgICAgIG51bV9jb2x1bW5zID0gNCwKICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJkYXRhIikKcGxvdApwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiX2x5bXBob2N5dGVNYXJrZXJzX1VNQVAucGRmIiwgc2VwID0gIiIpLAogICAgaGVpZ2h0ID0gY2VpbGluZyhsZW5ndGgoZ2VuZUNvZGVzKS80KSo2LCB3aWR0aCA9IDI0KQpwbG90CmRldi5vZmYoKQpgYGAKCgpNZXNlbmNoeW1lOgoKYGBge3J9CmdlbmVDb2RlcyA8LSBjKCJEQ04iLCJDT0wxQTIiLCJDT0wzQTEiLCJISElQIiwKICAgICAgICAgICAgICAgIkNBTENSTCIsIlNQQVJDIiwiUkJQMSIsIkNPTDFBMSIsCiAgICAgICAgICAgICAgICJJR0ZCUDMiLCAiSUdGQlA3IikKZ2VuZUNvZGVzIDwtIGMoIkNPTDFBMiIsICJDT0wzQTEiLCAiSUdGQlA3IiwgIklHRkJQMyIsIAogICAgICAgICAgICAgICAiRENOIiwgIkNBTENSTCIsICJDT0wxQTEiLCAiU1BBUkMiLCAKICAgICAgICAgICAgICAgIlJCUDEiLCAiSEhJUCIsIlJCUDEiLCJMUkFUIiwKICAgICAgICAgICAgICAgIlBERTNCIiwiSEdGIiwiQ05OMiIsIkFDVEEyIikKcGxvdCA8LSBGZWF0dXJlUGxvdF9zY0N1c3RvbShzb2JqLAogICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmVDb2RlcywKICAgICAgICAgICAgICAgICAgICAgY29sb3JzX3VzZSA9IHZpcmlkaXNfbGlnaHRfaGlnaCwKICAgICAgICAgICAgICAgICAgICAgbnVtX2NvbHVtbnMgPSA0KQpwbG90CnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfbWVzZW5jaHltYWxNYXJrZXJzX1VNQVAucGRmIiwgc2VwID0gIiIpLAogICAgaGVpZ2h0ID0gY2VpbGluZyhsZW5ndGgoZ2VuZUNvZGVzKS80KSo2LCB3aWR0aCA9IDI0KQpwbG90CmRldi5vZmYoKQpgYGAKCkNob2xhbmdpb2N5dGVzOgoKYGBge3J9CmdlbmVDb2RlcyA8LSBjKCJLUlQxOSIsIlNMQzRBNCIsIkNGVFIiLCJFUENBTSIpCmdlbmVDb2RlcyA8LSBjKCJBTlhBMiIsICJDU1QzIiwgIkJJUkMzIiwgIlRFU0MiLAogICAgICAgICAgICAgICAiS1JUMTkiLCAiU09YOSIsICJFUENBTSIsIlNMQzRBNCIsCiAgICAgICAgICAgICAgICJDRlRSIikKcGxvdCA8LSBGZWF0dXJlUGxvdF9zY0N1c3RvbShzb2JqLAogICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmVDb2RlcywKICAgICAgICAgICAgICAgICAgICAgY29sb3JzX3VzZSA9IHZpcmlkaXNfbGlnaHRfaGlnaCwKICAgICAgICAgICAgICAgICAgICAgbnVtX2NvbHVtbnMgPSA0KQpwbG90CnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfY2hvbGFuZ2lvY3l0ZU1hcmtlcnNfVU1BUC5wZGYiLCBzZXAgPSAiIiksCiAgICBoZWlnaHQgPSBjZWlsaW5nKGxlbmd0aChnZW5lQ29kZXMpLzQpKjYsIHdpZHRoID0gMjQpCnBsb3QKZGV2Lm9mZigpCmBgYAoKTXllbG9pZCBjZWxscwoKYGBge3J9CmdlbmVDb2RlcyA8LSBjKCJUWVJPQlAiLCJDRDc0IiwiQ1RTUyIsIlZTSUc0IiwKICAgICAgICAgICAgICAgIk1BUkNPIiwgIkNENUwiLCJITU9YMSIsIlZDQU0xIiwKICAgICAgICAgICAgICAgIklUR0FNIiwiRkNHUjNBO0ZDR1IzQiIsIkZjZ3IzO0ZjZ3IyYiIsIkNUU0EiLAogICAgICAgICAgICAgICAiSUwxN1JBLTEiLCJTSVJQQTtTSVJQQjE7U0lSUEciLCJCVExBIiwgIkNBRE0xIiwKICAgICAgICAgICAgICAgIklEMiIsIkxZNkUiLCJGTFQzIiwgIkNEMTQiLAogICAgICAgICAgICAgICAiTk9UQ0gyIiwiTFlaLTEiLCJTMTAwQTgiKQpwbG90IDwtIEZlYXR1cmVQbG90X3NjQ3VzdG9tKHNvYmosCiAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gZ2VuZUNvZGVzLAogICAgICAgICAgICAgICAgICAgICBjb2xvcnNfdXNlID0gdmlyaWRpc19saWdodF9oaWdoLAogICAgICAgICAgICAgICAgICAgICBudW1fY29sdW1ucyA9IDQpCnBsb3QKcGRmKHBhc3RlKCIuL2ZpZ3VyZXMvIiwgdGlzc3VlLCAiLyIsIHRpc3N1ZSwgIl9teWVsb2lkTWFya2Vyc19VTUFQLnBkZiIsIHNlcCA9ICIiKSwKICAgIGhlaWdodCA9IGNlaWxpbmcobGVuZ3RoKGdlbmVDb2RlcykvNCkqNiwgd2lkdGggPSAyNCkKcGxvdApkZXYub2ZmKCkKYGBgCgoKIyMgQ29ycmVsYXRpb24gcGxvdHMKCkdlbmVyYXRlIGhlYXRtYXBzIGNvbXBhcmluZyB3b29kY2h1Y2sgY2x1c3RlcnMgd2l0aCB2YXJpb3VzIGRhdGFzZXRzCgojIyMgU2V0dXAgZm9yIGFsbCBjb3JyZWxhdGlvbnMKCkZpcnN0LCBzZXQgdXAgd2hhdGV2ZXIgd29vZGNodWNrIGRhdGFzZXQgSSBhbSB3b3JraW5nIHdpdGggYnkgcmVhZGluZyBpbiB0aGUgb3J0aG9sb2cgdGFibGUsIGNob29zaW5nIHdoZXRoZXIgdGhlIG9ydGhvbG9ncyB0byB1c2UgYXJlIGh1bWFuLCBtb3VzZSwgb3Igd29vZGNodWNrLCBhbmQgY2FsY3VsYXRpbmcgdGhlIGF2ZXJhZ2UgZXhwcmVzc2lvbiBmb3IgZWFjaCBjbHVzdGVyLiBUaGUgb3V0cHV0IG9mIHRoaXMgc2VjdGlvbiBpcyB0aGUgc2NhbGVkIGNsdXN0ZXIgZ2VuZS1leHByZXNzaW9uIG1hdHJpeAoKYGBge3J9CiNncm91cHMgPC0gcmVzCmdyb3VwcyA8LSAiZ2VuZXJhbF9jZWxsX2xhYmVscyIKIyBSZWFkIGluIG9ydGhvbG9nIHRhYmxlCmdlbmVOYW1lVGFibGUgPC0gcmVhZC50YWJsZSgifi9Ecm9wYm94L1pvZS9zY2ZfdmVyc2lvbi9tYWtlX2d0Zi9vcnRob2ZpbmRlcl9zYzIvaG9tb2xvZ2VuZS9jb2xsZWN0ZWRPcnRob2ZpbmRlclBhaXJpbmdzLnRzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiXHQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSkKd29vZGNodWNrQ2x1c3RlckF2ZXJhZ2VzIDwtIEF2ZXJhZ2VFeHByZXNzaW9uKHNvYmosCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheXMgPSAiU0NUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAic2NhbGUuZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9IGdyb3VwcykKIyBTY2FsZSBkYXRhCndvb2RjaHVja0NsdXN0ZXJBdmVyYWdlcyRTQ1QgPC0gbmEub21pdCh0KHNjYWxlKHQoYXMubWF0cml4KHdvb2RjaHVja0NsdXN0ZXJBdmVyYWdlcyRTQ1QpKSkpKQojIEdyYWIgZ2VuZSBuYW1lcyBmcm9tIFNldXJhdCBvYmplY3QKdW5pcXVlSGllciA8LSByb3cubmFtZXMod29vZGNodWNrQ2x1c3RlckF2ZXJhZ2VzJFNDVCkKdW5pcXVlSGllciA8LSBhcy5kYXRhLmZyYW1lKHVuaXF1ZUhpZXIpCiMgQmluZCB3aXRoIGdlbmVOYW1lVGFibGUgdG8gZ2V0IGNvcnJlY3Qgb3JkZXIgKG5vdGljZSB1bmlxdWVIaWVyIGlzIG9uIGxlZnQpCm5ld05hbWVzIDwtIGRwbHlyOjpsZWZ0X2pvaW4odW5pcXVlSGllciwgZ2VuZU5hbWVUYWJsZSwgYnkgPSAidW5pcXVlSGllciIpCiMgR2V0IG9ydGhvbG9ncyBmcm9tIGVpdGhlciBtb3VzZSBvciBodW1hbgpzcGVjaWVzIDwtICJodW1hbiIKaWYgKHNwZWNpZXMgPT0gImh1bWFuIikgewogICMgSWYgaHVtYW4gb25lLXRvLW9uZSBvcnRobyBoYXMgTkEsIHJlcGxhY2Ugd2l0aCBtaWthZG9fZmluYWxfc2MyX3N0cmluZ2VudF9ub01pdG9fcHJvdGVpbiBjb2x1bW4KICAjIFRoaXMgaXMgdG8gYXZvaWQgYW5kIHBvdGVudGlhbCBtaXN0YWtlcyBpbiByZWNvZ25pemluZyB0aGluZ3MgaXQgc2hvdWxkbid0IGJlIHJlY29nbml6aW5nCiAgbmV3TmFtZXMkc3BlY2llc09uZVRvT25lIDwtIGlmZWxzZShpcy5uYShuZXdOYW1lcyRodW1hbk9uZVRvT25lKSwgbmV3TmFtZXMkdW5pcXVlSGllciwgbmV3TmFtZXMkaHVtYW5PbmVUb09uZSkKfSBlbHNlIGlmIChzcGVjaWVzID09ICJtb3VzZSIpIHsKICBuZXdOYW1lcyRzcGVjaWVzT25lVG9PbmUgPC0gaWZlbHNlKGlzLm5hKG5ld05hbWVzJG1vdXNlT25lVG9PbmUpLCBuZXdOYW1lcyR1bmlxdWVIaWVyLCBuZXdOYW1lcyRtb3VzZU9uZVRvT25lKQp9IGVsc2UgaWYgKHNwZWNpZXMgPT0gIndvb2RjaHVjayIpIHsKICBuZXdOYW1lcyRzcGVjaWVzT25lVG9PbmUgPC0gbmV3TmFtZXMkdW5pcXVlSGllcgp9CiMgR3JhYiBkYXRhZnJhbWUKd29vZGNodWNrQ2x1c3RlckF2ZXJhZ2VzIDwtIHdvb2RjaHVja0NsdXN0ZXJBdmVyYWdlcyRTQ1QKIyBSZXBsYWNlIG5hbWVzIHdpdGggb25lLXRvLW9uZSBvcnRob2xvZ3VlIG9mIHBhcnRpY3VsYXIgc3BlY2llcwpyb3cubmFtZXMod29vZGNodWNrQ2x1c3RlckF2ZXJhZ2VzKSA8LSBuZXdOYW1lcyRzcGVjaWVzT25lVG9PbmUKIyBNYWtlIHN1cmUgZm9ybWF0dGVkIGNvcnJlY3RseQp3b29kY2h1Y2tDbHVzdGVyQXZlcmFnZXMgPC0gYXMuZGF0YS5mcmFtZSh3b29kY2h1Y2tDbHVzdGVyQXZlcmFnZXMpCiMgT3JkZXIgYnkgZ2VuZSBuYW1lCndvb2RjaHVja0NsdXN0ZXJBdmVyYWdlcyA8LSB3b29kY2h1Y2tDbHVzdGVyQXZlcmFnZXNbb3JkZXIocm93Lm5hbWVzKHdvb2RjaHVja0NsdXN0ZXJBdmVyYWdlcykpLF0KIyBTYW5pdHkgY2hlY2sKaGVhZCh3b29kY2h1Y2tDbHVzdGVyQXZlcmFnZXMpCmBgYAoKIyMjIERhdGFzZXQtc3BlY2lmaWMgc2V0dXAKCkNvcnJlbGF0aW9uIG9mIHdvb2RjaHVjayBQQk1DcyB3aXRoIGh1bWFuIDY4ayBQQk1DIGRhdGFzZXQgZnJvbSAxMFggR2Vub21pY3MKCmBgYHtyfQojIE5vdyBuZWVkIHRvIHJlYWQgaW4gNjhLIFBCTUMgZGF0YQpodW1hblBCTUMgPC0gcmVhZC5jc3YoIn4vRHJvcGJveC9ab2Uvc2NmX3ZlcnNpb24vYW5hbHlzaXMvY29ycmVsYXRpb25UZXN0cy82OEtfcGJtY19kYXRhLzY4S19lbnJpY2hlZEdlbmVzLmNzdiIsCiAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBGQUxTRSkKIyBHZXQgcmlkIG9mIHRvcCByb3cKaHVtYW5QQk1DIDwtIGh1bWFuUEJNQ1stMSxdCiMgU2VwYXJhdGUgYWxsIGNlbGwgYW5kIG15bG9pZCBjZWxsIGRhdGEKYWxsQ2VsbHMgPC0gc2VsZWN0KGh1bWFuUEJNQywgVjEsIFYyLCBWMykKbXllbG9pZCA8LSBzZWxlY3QoaHVtYW5QQk1DLCBWNSwgVjYsIFY3KQojIFJlbmFtZSBhbmQgZ2V0IHJpZCBvZiBmaXJzdCByb3cKY29sbmFtZXMoYWxsQ2VsbHMpIDwtIGMoIkNsdXN0ZXIiLCAiR2VuZSIsICJFbnJpY2htZW50IikKY29sbmFtZXMobXllbG9pZCkgPC0gYygiQ2x1c3RlciIsICJHZW5lIiwgIkVucmljaG1lbnQiKQojIEdldCByaWQgb2YgdG9wIHJvdwphbGxDZWxscyA8LSBhbGxDZWxsc1stMSxdCm15ZWxvaWQgPC0gbXllbG9pZFstMSxdCiMgSSBjYW4gdGhlbiBmaWx0ZXIgdGhlIHJvd3MgYW5kIGJpbmQgdGhlIGRhdGEgZnJhbWVzIGJhY2sgdG9nZXRoZXIgYnkgZ2VuZSBuYW1lCmZvciAoaiBpbiAxOjEwKSB7CiAgZGF0IDwtIGRwbHlyOjpmaWx0ZXIoYWxsQ2VsbHMsIENsdXN0ZXIgPT0gaikKICAjZGF0IDwtIGdldChwYXN0ZSgiYWxsQ2VsbHMiLCBqLCBzZXAgPSAiIikpCiAgIyBNdWx0aXBseSBlbnJpY2htZW50IHZhbHVlcyBieSAtMSBiZWNhdXNlIHRoZSBzaWducyBhcmUgYmFja3dhcmRzPz8/CiAgZGF0JEVucmljaG1lbnQgPC0gYXMubnVtZXJpYyhkYXQkRW5yaWNobWVudCkgKiAtMQogIGRhdCA8LSBkcGx5cjo6c2VsZWN0KGRhdCwgR2VuZSwgRW5yaWNobWVudCkKICBjb2xuYW1lcyhkYXQpIDwtIGMoIkdlbmUiLCBwYXN0ZSgiRW5yaWNobWVudCIsIGosIHNlcCA9ICIiKSkKICBpZiAoaiA9PSAxKSB7CiAgICBhbGxDZWxsc01hdHJpeCA8LSBkYXQKICB9CiAgZWxzZSB7CiAgICBhbGxDZWxsc01hdHJpeCA8LSBkcGx5cjo6ZnVsbF9qb2luKGFsbENlbGxzTWF0cml4LCBkYXQsIGJ5ID0gIkdlbmUiKQogIH0KfQojIE1ha2Ugcm93IG5hbWVzIGdlbmUgbmFtZXMKcm93bmFtZXMoYWxsQ2VsbHNNYXRyaXgpIDwtIGFsbENlbGxzTWF0cml4JEdlbmUKYWxsQ2VsbHNNYXRyaXggPC0gZHBseXI6OnNlbGVjdChhbGxDZWxsc01hdHJpeCwgLUdlbmUpCiMgTWFrZSBjb2x1bW4gbmFtZXMgY2VsbCB0eXBlcwpjb2xuYW1lcyhhbGxDZWxsc01hdHJpeCkgPC0gYygiQWN0aXZhdGVkIENEOCsiLCAiTmFpdmUgQ0Q4KyIsICJNZW1vcnkgYW5kIFJlZyBUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5haXZlIENENCsiLCAiTksiLCAiQ0Q4KyIsICJCIiwgIk1lZ2FrYXJ5b2N5dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vbm9jeXRlcyBhbmQgRGVuZHJpdGljIiwgIkIsIERlbmRyaXRpYywgVCIpCiMgU2NhbGUgYWNyb3NzIGNvbHVtbnMKYWxsQ2VsbHNNYXRyaXggPC0gdChzY2FsZSh0KGFsbENlbGxzTWF0cml4KSkpCiMgT3JkZXIgZ2VuZXMgYWxwaGFiZXRpY2FsbHkgYnkgZ2VuZSBuYW1lCmFsbENlbGxzTWF0cml4IDwtIGFsbENlbGxzTWF0cml4W29yZGVyKHJvdy5uYW1lcyhhbGxDZWxsc01hdHJpeCkpLF0KIyBTYW5pdHkgY2hlY2sKaGVhZChhbGxDZWxsc01hdHJpeCkKc3BlY2llc0RhdGEgPC0gIjY4S1BCTUMiCmBgYAoKQ29ycmVsYXRpb24gb2Ygd29vZGNodWNrIGxpdmVyIHdpdGggaHVtYW4gbGl2ZXIgZGF0YXNldCBmcm9tIE1hY1BhcmxhbmQgKmV0IGFsLiogKDIwMTgpCgpgYGB7cn0KIyBGaW5kIGNsdXN0ZXIgYXZlcmFnZXMgb2YgaHVtYW4gbGl2ZXIgZGF0YQpsb2FkKCJ+L0Ryb3Bib3gvWm9lL3NjZl92ZXJzaW9uL2FuYWx5c2lzL2NvcnJlbGF0aW9uVGVzdHMvSHVtYW5MaXZlci5SRGF0YSIpCiMgUnVuIFNDVHJhbnNmb3JtCkh1bWFuTGl2ZXJTZXVyYXQgPC0gVXBkYXRlU2V1cmF0T2JqZWN0KEh1bWFuTGl2ZXJTZXVyYXQpCkh1bWFuTGl2ZXJTZXVyYXQgPC0gU0NUcmFuc2Zvcm0oSHVtYW5MaXZlclNldXJhdCkKaHVtYW5DbHVzdGVyQXZlcmFnZXMgPC0gQXZlcmFnZUV4cHJlc3Npb24oSHVtYW5MaXZlclNldXJhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlzID0gIlNDVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAic2NhbGUuZGF0YSIpCiMgUmVwbGFjZSBjbHVzdGVyIG51bWJlcnMgd2l0aCBuYW1lcwpjb2xuYW1lcyhodW1hbkNsdXN0ZXJBdmVyYWdlcyRTQ1QpIDwtIGMoIkhlcCAxIiwgIkFscGhhLWJldGEgVCBjZWxscyIsICJIZXAgMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5mbGFtbWF0b3J5IG1hY3MiLCAiSGVwIDMiLCAiSGVwIDQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBsYXNtYSBjZWxscyIsICJOSy1saWtlIGNlbGxzIiwgIkdhbW1hLWRlbHRhIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vbi1pbmZsYW1tYXRvcnkgbWFjcyIsICJQZXJpcG9ydGFsIExTRUNzIiwgIkNlbnRyYWwgdmVub3VzIExTRUNzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQb3J0YWwgZW5kb3RoZWxpYWwgY2VsbHMiLCAiSGVwIDUiLCAiSGVwIDYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hdHVyZSBCIGNlbGxzIiwgIkNob2xhbmdpb2N5dGVzIiwgIkdhbW1hLWRlbHRhIFQgY2VsbHMgMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXJ5dGhyb2lkIGNlbGxzIiwgIkhlcGF0aWMgc3RlbGxhdGUgY2VsbHMiKQojIElmIG9ubHkgbG9va2luZyBhdCBzcGVjaWZpYyBjbHVzdGVycwojaHVtYW5DbHVzdGVyQXZlcmFnZXMkU0NUIDwtIGh1bWFuQ2x1c3RlckF2ZXJhZ2VzJFNDVFssYygiMyIsIjEiLCIxNSIsIjYiLCIxNCIsIjUiKV0KIyBPdGhlcndpc2UgZ28gc3RyYWlnaHQgdG8gaGVyZToKaHVtYW5DbHVzdGVyQXZlcmFnZXMkU0NUIDwtIG5hLm9taXQodChzY2FsZSh0KGFzLm1hdHJpeChodW1hbkNsdXN0ZXJBdmVyYWdlcyRTQ1QpKSkpKQojIEdyYWIgZ2VuZSBuYW1lcwpodW1hbkdlbmVzIDwtIHJvdy5uYW1lcyhodW1hbkNsdXN0ZXJBdmVyYWdlcyRTQ1QpCiMgTm93IHR1cm4gaW50byBsYXJnZSBkYXRhZnJhbWUKYWxsQ2VsbHNNYXRyaXggPC0gYXMuZGF0YS5mcmFtZShodW1hbkNsdXN0ZXJBdmVyYWdlcyRTQ1QpCiMgT3JkZXIgYnkgcm93IG5hbWUKYWxsQ2VsbHNNYXRyaXggPC0gYWxsQ2VsbHNNYXRyaXhbb3JkZXIocm93Lm5hbWVzKGFsbENlbGxzTWF0cml4KSksXQojIFNhbml0eSBjaGVjawpoZWFkKGFsbENlbGxzTWF0cml4KQpzcGVjaWVzRGF0YSA8LSAibWFjcGFybGFuZCIKYGBgCgpDb3JyZWxhdGlvbiBvZiB3b29kY2h1Y2sgbGl2ZXIgd2l0aCBodW1hbiBsaXZlciBkYXRhc2V0IGZyb20gQWl6YXJhbmkgKmV0IGFsLioKCmBgYHtyfQojIFJlYWQgaW4gQWl6YXJhbmkgZGF0YXNldAphaXphcmFuaSA8LSByZWFkUkRTKCJ+L0Ryb3Bib3gvWm9lL3NjZl92ZXJzaW9uL2FuYWx5c2lzL2NvcnJlbGF0aW9uVGVzdHMvR1NFMTI0Mzk1X05vcm1hbGh1bWFubGl2ZXJkYXRhLlJEYXRhIikKIyBSZWFkIGluIGNsdXN0ZXJzIGFuZCBsYWJlbCBjZWxscwphaXphcmFuaUNsdXN0ZXJzIDwtIHJlYWQudGFibGUoIn4vRHJvcGJveC9ab2Uvc2NmX3ZlcnNpb24vYW5hbHlzaXMvY29ycmVsYXRpb25UZXN0cy9HU0UxMjQzOTVfY2x1c3RlcnBhcnRpdGlvbi50eHQiKQojIE9ubHkga2VlcCBjZWxscyBpbiB0aGUgY2x1c3RlciBvYmplY3QKYWl6YXJhbmkgPC0gYWl6YXJhbmlbLGludGVyc2VjdChjb2xuYW1lcyhhaXphcmFuaSkscm93Lm5hbWVzKGFpemFyYW5pQ2x1c3RlcnMpKV0KIyBDcmVhdGUgU2V1cmF0IG9iamVjdAphaXphcmFuaSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gYWl6YXJhbmkpCiMgUnVuIFNDVHJhbnNmb3JtCmFpemFyYW5pIDwtIFNDVHJhbnNmb3JtKGFpemFyYW5pKQojIEFkZCBjbHVzdGVyIElEcwpJZGVudHMoYWl6YXJhbmkpIDwtIGFpemFyYW5pQ2x1c3RlcnMkc2N0LmNwYXJ0CiMgR2V0IGNsdXN0ZXIgYXZlcmFnZXMKYWl6YXJhbmlBdmVyYWdlcyA8LSBBdmVyYWdlRXhwcmVzc2lvbihhaXphcmFuaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheXMgPSAiU0NUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gInNjYWxlLmRhdGEiKQphaXphcmFuaUF2ZXJhZ2VzJFNDVCA8LSBuYS5vbWl0KHQoc2NhbGUodChhcy5tYXRyaXgoYWl6YXJhbmlBdmVyYWdlcyRTQ1QpKSkpKQojIEdyYWIgZ2VuZSBuYW1lcwphaXphcmFuaUdlbmVzIDwtIHJvdy5uYW1lcyhhaXphcmFuaUF2ZXJhZ2VzJFNDVCkKIyBOb3cgdHVybiBpbnRvIGxhcmdlIGRhdGFmcmFtZQphbGxDZWxsc01hdHJpeCA8LSBhcy5kYXRhLmZyYW1lKGFpemFyYW5pQXZlcmFnZXMkU0NUKQojIE9yZGVyIGJ5IGNvbHVtbgphbGxDZWxsc01hdHJpeCA8LSBhbGxDZWxsc01hdHJpeFssYXMuY2hhcmFjdGVyKHNvcnQoYXMubnVtZXJpYyhjb2xuYW1lcyhhbGxDZWxsc01hdHJpeCkpKSldCiMgUmVuYW1lIGNvbHVtbnMgdG8gYmUgbW9yZSBtZWFuaW5nZnVsIChub3QgdG90YWxseSBjb25maWRlbnQgSSBnb3QgYWxsIGNvcnJlY3QpCmNvbG5hbWVzKGFsbENlbGxzTWF0cml4KSA8LSBjKCdOSywgTktUIGFuZCBUIGNlbGxzICgxKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdLdXBmZmVyIGNlbGxzICgyKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdOSywgTktUIGFuZCBUIGNlbGxzICgzKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdFUENBTSsgY2VsbHMgYW5kIGNob2xhbmdpb2N5dGVzICg0KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdOSywgTktUIGFuZCBUIGNlbGxzICg1KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdLdXBmZmVyIGNlbGxzICg2KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdFUENBTSsgY2VsbHMgYW5kIGNob2xhbmdpb2N5dGVzICg3KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdCIGNlbGxzICg4KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMaXZlciBzaW51c29pZGFsIGVuZG90aGVsaWFsIGNlbGxzICg5KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdNYWNyb3Zhc2N1bGFyIGVuZG90aGVsaWFsIGNlbGxzICgxMCknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSGVwYXRvY3l0ZXMgKDExKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdOSywgTktUIGFuZCBUIGNlbGxzICgxMiknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTGl2ZXIgc2ludXNvaWRhbCBlbmRvdGhlbGlhbCBjZWxscyAoMTMpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0hlcGF0b2N5dGVzICgxNCknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnT3RoZXIgZW5kb3RoZWxpYWwgY2VsbHMgKDE1KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdPdGhlciAoMTYpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0hlcGF0b2N5dGVzICgxNyknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTkssIE5LVCBhbmQgVCBjZWxscyAoMTgpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ05LLCBOS1QgYW5kIFQgY2VsbHMgKDE5KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMaXZlciBzaW51c29pZGFsIGVuZG90aGVsaWFsIGNlbGxzICgyMCknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTWFjcm92YXNjdWxhciBlbmRvdGhlbGlhbCBjZWxscyAoMjEpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0IgY2VsbHMgKDIyKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdLdXBmZmVyIGNlbGxzICgyMyknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRVBDQU0rIGNlbGxzIGFuZCBjaG9sYW5naW9jeXRlcyAoMjQpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0t1cGZmZXIgY2VsbHMgKDI1KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdPdGhlciBlbmRvdGhlbGlhbCBjZWxscyAoMjYpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ090aGVyICgyNyknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTkssIE5LVCBhbmQgVCBjZWxscyAoMjgpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ01hY3JvdmFzY3VsYXIgZW5kb3RoZWxpYWwgY2VsbHMgKDI5KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdIZXBhdG9jeXRlcyAoMzApJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0t1cGZmZXIgY2VsbHMgKDMxKScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdNYWNyb3Zhc2N1bGFyIGVuZG90aGVsaWFsIGNlbGxzICgzMiknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnU3RlbGxhdGUgY2VsbHMgYW5kIG15b2ZpYnJvYmxhc3RzICgzMyknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQiBjZWxscyAoMzQpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ090aGVyIGVuZG90aGVsaWFsIGNlbGxzICgzNSknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnT3RoZXIgKDM2KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdPdGhlciAoMzcpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0IgY2VsbHMgKDM4KScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdFUENBTSsgY2VsbHMgYW5kIGNob2xhbmdpb2N5dGVzICgzOSknKQojIE9yZGVyIGJ5IHJvdyBuYW1lCmFsbENlbGxzTWF0cml4IDwtIGFsbENlbGxzTWF0cml4W29yZGVyKHJvdy5uYW1lcyhhbGxDZWxsc01hdHJpeCkpLF0KIyBTYW5pdHkgY2hlY2sKaGVhZChhbGxDZWxsc01hdHJpeCkKc3BlY2llc0RhdGEgPC0gImFpemFyYW5pIgpgYGAKCkNvcnJlbGF0aW9uIG9mIHdvb2RjaHVjayBsaXZlciB3aXRoIGh1bWFuIGxpdmVyIGRhdGFzZXQgZnJvbSBBbmRyZXdzICpldCBhbC4qICgyMDIyKQoKYGBge3J9CiMgTG9hZCBkYXRhc2V0Cmh1bWFuTnVjIDwtIHJlYWRSRFMoIn4vRHJvcGJveC9ab2Uvc2NmX3ZlcnNpb24vYW5hbHlzaXMvY29ycmVsYXRpb25UZXN0cy9zaW5nbGVfbnVjXzIwX2h1bWFuX21hcC5yZHMiKQojIElzb2xhdGUgc2luZ2xlLW51YyBvbmx5Cmh1bWFuTnVjIDwtIFVwZGF0ZVNldXJhdE9iamVjdChodW1hbk51YykKaHVtYW5OdWMgPC0gc3Vic2V0KGh1bWFuTnVjLCBzdWJzZXQgPSBhc3NheV90eXBlID09ICJzaW5nbGVfbnVjIikKIyBSdW4gU0NUcmFuc2Zvcm0KaHVtYW5OdWMgPC0gU0NUcmFuc2Zvcm0oaHVtYW5OdWMpCiMgQ2hhbmdlIGlkZW50cwpJZGVudHMoaHVtYW5OdWMpIDwtIGh1bWFuTnVjQG1ldGEuZGF0YSRzdWJfYW5ub3RhdGlvbgojIEdldCBjbHVzdGVyIGF2ZXJhZ2VzCmh1bWFuTnVjQ2x1c3RBdmVyYWdlcyA8LSBBdmVyYWdlRXhwcmVzc2lvbihodW1hbk51YywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5cyA9ICJTQ1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJzY2FsZS5kYXRhIikKaHVtYW5OdWNDbHVzdEF2ZXJhZ2VzJFNDVCA8LSBuYS5vbWl0KHQoc2NhbGUodChhcy5tYXRyaXgoaHVtYW5OdWNDbHVzdEF2ZXJhZ2VzJFNDVCkpKSkpCiMgR3JhYiBnZW5lIG5hbWVzCm51Y0dlbmVzIDwtIHJvdy5uYW1lcyhodW1hbk51Y0NsdXN0QXZlcmFnZXMkU0NUKQojIE5vdyB0dXJuIGludG8gbGFyZ2UgZGF0YWZyYW1lCmFsbENlbGxzTWF0cml4IDwtIGFzLmRhdGEuZnJhbWUoaHVtYW5OdWNDbHVzdEF2ZXJhZ2VzJFNDVCkKIyBPcmRlciBieSByb3cgbmFtZQphbGxDZWxsc01hdHJpeCA8LSBhbGxDZWxsc01hdHJpeFtvcmRlcihyb3cubmFtZXMoYWxsQ2VsbHNNYXRyaXgpKSxdCiMgU2FuaXR5IGNoZWNrCmhlYWQoYWxsQ2VsbHNNYXRyaXgpCnNwZWNpZXNEYXRhIDwtICJhbmRyZXdzIgpgYGAKCgpDb3JyZWxhdGlvbiBvZiB3b29kY2h1Y2sgbGl2ZXIgd2l0aCB3b29kY2h1Y2sgUEJNQ3MuIEZvciB0aGlzIGNvcnJlbGF0aW9uLCByZWFkIGluIHRoZSB3b29kY2h1Y2sgbGl2ZXIgZGF0YXNldCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoaXMgc2NyaXB0IGFuZCB0aGVuIHJlYWQgaW4gdGhlIHdvb2RjaHVjayBQQk1DcyBiZWxvdwoKYGBge3J9Cmdyb3VwcyA8LSAiZ2VuZXJhbF9jZWxsX2xhYmVscyIKIyBTdGFydCB3aXRoIGxpdmVyIGFuZCByZWFkIGluIHdvb2RjaHVjayBQQk1DcyBhZ2Fpbgpsb2FkKCJ+L0Ryb3Bib3gvWm9lL3NjZl92ZXJzaW9uL2FuYWx5c2lzL2hlYWx0aHlfc2Mvc2V1cmF0X29iamVjdHMvbm9fZHJvcGxldFFDL2ludGVncmF0ZWRfUEJNQ19jY2Ffa2FuY2hvcjVfc2NDbHVzdFZpei5SRGF0YSIpCklkZW50cyhzY1NldXJhdCkgPC0gImludGVncmF0ZWRfc25uX3Jlcy4wLjYiCiMgRmluZCBjbHVzdGVyIGF2ZXJhZ2VzCnBibWNDbHVzdGVyQXZlcmFnZXMgPC0gQXZlcmFnZUV4cHJlc3Npb24oc2NTZXVyYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlzID0gIlNDVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJzY2FsZS5kYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9IGdyb3VwcykKcGJtY0NsdXN0ZXJBdmVyYWdlcyA8LSBhcy5kYXRhLmZyYW1lKG5hLm9taXQodChzY2FsZSh0KGFzLm1hdHJpeChwYm1jQ2x1c3RlckF2ZXJhZ2VzJFNDVCkpKSkpKQojIE9yZGVyIGJ5IHJvdyBuYW1lCmFsbENlbGxzTWF0cml4IDwtIHBibWNDbHVzdGVyQXZlcmFnZXNbb3JkZXIocm93Lm5hbWVzKHBibWNDbHVzdGVyQXZlcmFnZXMpKSxdCnNwZWNpZXNEYXRhIDwtICJQQk1DIgpgYGAKCiMjIyBPdXRwdXQgcGxvdHMgZm9yIGFsbCBjb3JyZWxhdGlvbnMKCmBgYHtyfQojIE5vdyBmaW5kIGludGVyc2VjdGluZyBnZW5lcwptYXRjaGVzIDwtIGludGVyc2VjdChyb3cubmFtZXMoYWxsQ2VsbHNNYXRyaXgpLAogICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMod29vZGNodWNrQ2x1c3RlckF2ZXJhZ2VzKSkKIyBMb29rIGF0IGhvdyBtYW55IGdlbmVzIG1hdGNoZWQKbGVuZ3RoKG1hdGNoZXMpCiMgTWFrZSBuZXcgbWF0cmljZXMgd2l0aCBvbmx5IG1hdGNoaW5nIGdlbmUgbmFtZXMKdG9Db3IgPC0gYWxsQ2VsbHNNYXRyaXhbbWF0Y2hlcyxdCndvb2RjaHVja0F2ZXJhZ2VzQ29yIDwtIHdvb2RjaHVja0NsdXN0ZXJBdmVyYWdlc1ttYXRjaGVzLF0KIyBEbyBQZWFyc29uCnBlYXJWYWwgPC0gY29yKHRvQ29yLCB3b29kY2h1Y2tBdmVyYWdlc0NvciwgbWV0aG9kID0gInBlYXJzb24iKQpoZWF0bWFwKHBlYXJWYWwpCiAgICAgICAgI21haW4gPSBwYXN0ZSgiUGVhcnNvbiBjb3JyZWxhdGlvbiBvZiIsIHNwZWNpZXNEYXRhLCAidnMiLCB3b29kY2h1Y2tEYXRhKSwKICAgICAgICAjeGxhYiA9IHdvb2RjaHVja0RhdGEsCiAgICAgICAgI3lsYWIgPSBzcGVjaWVzRGF0YSkKICAgICAgICAjbWFyZ2lucyA9IGMoNiwxMSkpCiNSb3d2ID0gTkEsCiNDb2x2ID0gTkEpCnBkZihwYXN0ZSgiLi9maWd1cmVzLyIsIHRpc3N1ZSwgIi8iLCB0aXNzdWUsICJfIiwgc3BlY2llc0RhdGEsICJfUGVhcnNvbkNvci5wZGYiLCBzZXAgPSAiIiksCiAgICBoZWlnaHQgPSAxNSwgd2lkdGggPSAxMykKaGVhdG1hcChwZWFyVmFsLCBtYXJnaW5zID0gYygxMywxMykpCmRldi5vZmYoKQojIERvIFNwZWFybWFuCnNwZWFyVmFsIDwtIGNvcih0b0Nvciwgd29vZGNodWNrQXZlcmFnZXNDb3IsIG1ldGhvZCA9ICJzcGVhcm1hbiIpCmhlYXRtYXAoc3BlYXJWYWwpCiAgICAgICAgI21haW4gPSBwYXN0ZSgiU3BlYXJtYW4gY29ycmVsYXRpb24gb2YiLCBzcGVjaWVzRGF0YSwgInZzIiwgd29vZGNodWNrRGF0YSksCiAgICAgICAgI3hsYWIgPSB3b29kY2h1Y2tEYXRhLAogICAgICAgICN5bGFiID0gc3BlY2llc0RhdGEpCiAgICAgICAgI21hcmdpbnMgPSBjKDYsMTEpKQojUm93diA9IE5BLAojQ29sdiA9IE5BKQpwZGYocGFzdGUoIi4vZmlndXJlcy8iLCB0aXNzdWUsICIvIiwgdGlzc3VlLCAiXyIsIHNwZWNpZXNEYXRhLCAiX1NwZWFybWFuQ29yLnBkZiIsIHNlcCA9ICIiKSwKICAgIGhlaWdodCA9IDE1LCB3aWR0aCA9IDEzKQpoZWF0bWFwKHNwZWFyVmFsLCBtYXJnaW5zID0gYygxMywxMykpCmRldi5vZmYoKQpgYGAKCgoKCg==